Click here to Skip to main content
15,888,351 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,
I trying to update a table with multiple columns in my C# project.My intention is to log values from electronics at regular interval(4sec). I was able to update table as i want and saving table value in .excel file.
It works fine for some time but after sometime the project will stuck, either i have to close or restart the PC. If i don't update the table then the project works fine for days.
I have a code to draw chart from table values, even i tried without chart drawing or without update chart function and only updating table even though it was same problem

It will work for 5 hours, updating table every 4 sec.

I have a code to update table like this.
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Steema.TeeChart;
using Steema.TeeChart.Styles;
using System.Windows.Forms;
using NativeExcel;

namespace SensorLog
{
  public class Log
   {
    private TChart _chart;
    private DataGridView _list;
    private DataTable _table = new DataTable("EngineeringData");
    private string _logFile;
    private long _recs = 0;
    private int _logs = 0;
    private IWorkbook book;
    private IWorksheet sheet;


    public Log(TChart chart, DataGridView list)
    {
        _chart = chart;
        _list = list;
        _list.DataSource = _table;
        MakeTable();
        book = Factory.CreateWorkbook();

        _logFile = "Log_"
            + DateTime.Now.Year.ToString()
            + "-"
            + DateTime.Now.Month.ToString()
            + "-"
            + DateTime.Now.Day.ToString()
            + "_"
            + DateTime.Now.Hour.ToString()
            + "-"
            + DateTime.Now.Minute.ToString()
            + "_.xls";
    }

    public void Start()
    {
        _table.Clear();
        _recs = 0;

        sheet = book.Worksheets.Add();

        AnalogSensor.NewAnalogSensorData
            += new EventHandler<AnalogSensorDataEventArgs>(AnalogSensor_NewAnalogSensorData);
    }

    public void Stop()
    {
        int i = 1;
        foreach (DataColumn c in _table.Columns)
        {
            sheet.Cells[1, i].Value = c.ColumnName;
            sheet.Cells[2, i++].Value = c.Caption;
        }
        book.SaveAs(_logFile);

        AnalogSensor.NewAnalogSensorData
            -= new EventHandler<AnalogSensorDataEventArgs>(AnalogSensor_NewAnalogSensorData);
    }

    void AnalogSensor_NewAnalogSensorData(object sender, AnalogSensorDataEventArgs e)
    {
        if (e.Data.Priority > 0)
        {
            if (_list.InvokeRequired)
                _list.Invoke((MethodInvoker)delegate { UpdateTable(e.Data); });
            else
                UpdateTable(e.Data);

            UpdateChart(e.Data);
        }
    }

    private void MakeTable()
    {
        DataColumn[] keys = new DataColumn[1];

        Type type = Type.GetType("System.UInt64");
        keys[0] = MakeColumn("Index", type, true);
        _table.PrimaryKey = keys;
        type = Type.GetType("System.DateTime");
        MakeColumn("DateTime", type, true);
        _list.Columns["DateTime"].Visible = false;
        type = Type.GetType("System.String");
        MakeColumn("Time", type, false);
        type = Type.GetType("System.Double");
        MakeColumn(SystemNames.PressA, type, false);
        MakeColumn(SystemNames.PressB, type, false);
        MakeColumn(SystemNames.AnalogA, type, false);
        MakeColumn(SystemNames.AnalogB, type, false);
        MakeColumn(SystemNames.AnalogC, type, false);
        MakeColumn(SystemNames.AnalogD, type, false);
        MakeColumn(SystemNames.TempA, type, false);
        MakeColumn(SystemNames.TempB, type, false);
        MakeColumn(SystemNames.TempC, type, false);
    }

    private DataColumn MakeColumn(string name, Type type, bool state)
    {
        DataColumn column = new DataColumn();
        column.ColumnName = name;
        column.DataType = type;
        column.AutoIncrement = false;
        column.Caption = name;
        column.ReadOnly = false;
        column.Unique = false;
        _table.Columns.Add(column);
        _list.Columns[name].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
        _list.Columns[name].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;

        return column;
    }

    private void UpdateTable(AnalogSensorData data)
    {
        DataRow row = _table.Rows.Find(_recs);
        if (row == null)
        {
            row = _table.NewRow();
            row["Index"] = _recs;
            row["DateTime"] = data.Time;
            row["Time"] = data.Time.ToLongTimeString();
            row[data.SystemName] = data.Eng;
            _logs = 1;
            _table.Rows.Add(row);
        }
        else
        {
            row[data.SystemName] = data.Eng;
            if (++_logs >= SensorUC.NumberOfActive)
            {
                int i = 1;
                foreach (var item in row.ItemArray)
                {
                    sheet.Cells[(int)_recs + 3, i++].Value = item;
                }
                book.SaveAs(_logFile);
                _recs++;
            }
        }
        if (!_list.Columns[data.SystemName].HeaderText.Equals(data.SensorName))
        {
            _table.Columns[data.SystemName].Caption = data.SensorName;
            _list.Columns[data.SystemName].HeaderText = data.SensorName;
        }
        _list.FirstDisplayedCell = _list.Rows[_list.Rows.Count - 1].Cells[0];
        _list.Update();
    }

    private void UpdateChart(AnalogSensorData data)
    {
        if (data.Line.DataSource == null)
        {
            if (_chart.InvokeRequired)
            {
                _chart.Invoke((MethodInvoker)delegate
                {
                    _chart.Series.Add(data.Line);
                    data.Line.DataSource = _table;
                });
            }
            else
            {
                _chart.Series.Add(data.Line);
                data.Line.DataSource = _table;
            }
        }
        if (_chart.InvokeRequired)
        {
            _chart.Invoke((MethodInvoker)delegate { data.Line.CheckDataSource(); });
        }
        else
        {
            data.Line.CheckDataSource();
        }
    }
}
}

Can someone help me what might be the reason? or how to prevent it?
Posted

1 solution

I think your response time of the code based on drawing(updating) is not fast enqough. you also do this in the same thread.

To solve make sure you check after the first check was done instead of rechecking every 4 seconds. If you program is 1 second to late it will end up in crashing ofcorse. which make sense if you trying to check data from 5 hours.

Try to set the timer every 15 seconds. You will see the result (I think it will crash after 10hours).
 
Share this answer
 
Comments
vebi1000 16-Nov-15 5:40am    
Yes exactly if i change it to 15 sec then it crash after 10 hours. If i extend it to 1 mint then it will work for almost two days. Do you mean i need another thread to update drawing?
Wessel Beulink 16-Nov-15 8:27am    
You need to check if your UpdateTable() is running. So if your timer passed the 4 seconds and your try to update and your table still updating it need to wait for next update. But this will end up in a waiting line. So you need to consider to update the tabel every xxx - minutes instead of 15 seconds. When the process is longer than your waiting timer you simply showing to much information.

you'll never be able to show that ammount of data in 1 table view. You need to work with pages each page max 1000 rows. running in another thread will only improve the updating speed. So the questions are: how much you need to show? and how often it needs to be updated?

for example:
1. show 1000 records(max) from that day than save it to text file and write a new table.
2. work with multiple pages. evrytime you hit more than 1000 records make a table page 2, than 3. etc.


The ammount you can handle is simple based on your computer speed. So if you are going to run it on multiple computers consider to make it less for computers slower than yours.
vebi1000 16-Nov-15 10:54am    
Hi Wessel,
Thanks for you reply,

I need to update table every 5 secs, i have to present data at this interval.
working with multple pages seems nice idea for me. Can you provide some example on how to create multiple pages each time when i hit 1000 records?
Regards,
vebi.
Wessel Beulink 17-Nov-15 5:10am    
There tons of tutorials out there. You simple create a new table and put you values inside it. Or you split your view. Figure out what best methode is for your application. To start of remove the drawing event of the table and use: myDataTable.AsEnumerable().Take(5).CopyToDataTable() this wil only show 5 instead of all. This will no longer crash your application.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900