DataGrid: Real-Time Updates using a DataSet

G

Guest

I have a SystemData class (Singleton class extends the DataSet) which has one Table (Trace: 4 Columns). I start a thread in its constructor which keeps on adding data to the table (simulating Real-Time data).

I have a form (Form1) in my C# project which has a DataGrid (DataGrid1). I have set the DataSource property of this grid to the "Trace" table created above.

I can see the data being added to the grid instantaneously but after some time the system hangs up and I see the following Stack Trace. It also hangs up if I try to change the Column width in the grid. I have no clue whats going on as I am not trying to set any tool tips.

********************Stack Trace***************************
system.windows.forms.dll!System.Windows.Forms.DataGridToolTip.CreateToolTipHandle() + 0x1db bytes
system.windows.forms.dll!System.Windows.Forms.DataGrid.ResetToolTip() + 0x44 bytes
system.windows.forms.dll!System.Windows.Forms.DataGrid.OnLayout(System.Windows.Forms.LayoutEventArgs levent = {System.Windows.Forms.LayoutEventArgs}) + 0xad bytes
system.windows.forms.dll!System.Windows.Forms.Control.PerformLayout(System.Windows.Forms.Control affectedControl = <undefined value>, string affectedProperty = null) + 0x7c bytes
system.windows.forms.dll!System.Windows.Forms.Control.PerformLayout() + 0xf bytes
system.windows.forms.dll!System.Windows.Forms.DataGridColumnStyle.set_Width(int value = 123) + 0x4f bytes
system.windows.forms.dll!System.Windows.Forms.DataGrid.ColResizeEnd(System.Windows.Forms.MouseEventArgs e = {X=158 Y=26 Button=Left}) + 0x19f bytes
system.windows.forms.dll!System.Windows.Forms.DataGrid.OnMouseUp(System.Windows.Forms.MouseEventArgs e = {X=158 Y=26 Button=Left}) + 0x7f bytes
system.windows.forms.dll!System.Windows.Forms.Control.WmMouseUp(System.Windows.Forms.Message m = {System.Windows.Forms.Message}, System.Windows.Forms.MouseButtons button = Left, int clicks = 1) + 0x261 bytes
system.windows.forms.dll!System.Windows.Forms.Control.WndProc(System.Windows.Forms.Message m = {System.Windows.Forms.Message}) + 0x49b bytes
system.windows.forms.dll!ControlNativeWindow.OnMessage(System.Windows.Forms.Message m = {System.Windows.Forms.Message}) + 0x13 bytes
system.windows.forms.dll!ControlNativeWindow.WndProc(System.Windows.Forms.Message m = {System.Windows.Forms.Message}) + 0xda bytes
system.windows.forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(int hWnd = 26871752, int msg = 514, int wparam = 0, int lparam = 1704094) + 0x3d bytes
system.windows.forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods+IMsoComponentManager.FPushMessageLoop(int dwComponentID = 1, int reason = -1, int pvLoopData = 0) + 0x349 bytes
system.windows.forms.dll!ThreadContext.RunMessageLoopInner(int reason = -1, System.Windows.Forms.ApplicationContext context = {System.Windows.Forms.ApplicationContext}) + 0x1f3 bytes
system.windows.forms.dll!ThreadContext.RunMessageLoop(int reason = -1, System.Windows.Forms.ApplicationContext context = {System.Windows.Forms.ApplicationContext}) + 0x50 bytes
system.windows.forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.Form mainForm = {Testing.Form1}) + 0x34 bytes
Testing.exe!Testing.Form1.Main() Line 122 C#

********************************************************
********************SystemData.cs**************************
using System;
using System.Data;
using System.Threading;
using System.Windows.Forms;

namespace Testing
{
public class SystemData : DataSet
{
#region Private Variables

private static SystemData m_instance = null;

#endregion

#region Public Constructor

private SystemData()
{
m_Write = new ManualResetEvent(true);

// Add Trace Table
DataTable dtTrace = new DataTable("Trace");

dtTrace.Columns.Add("Time Stamp", Type.GetType("System.String"));
dtTrace.Columns.Add("Module Name", Type.GetType("System.String"));
dtTrace.Columns.Add("Method Name", Type.GetType("System.String"));
dtTrace.Columns.Add("Message", Type.GetType("System.String"));

Tables.Add(dtTrace);

Thread m_SubscriptionThread = new Thread (new ThreadStart (FillData));
m_SubscriptionThread.Start();
}

#endregion

#region Public Methods

public static SystemData GetInstance()
{
if ( m_instance == null )
m_instance = new SystemData();

return m_instance;
}

#endregion

#region Private Methods

private void FillData()
{
while (true)
{
Tables["Trace"].Rows.Add ( new Object[] {DateTime.Now.ToString(), "Module", "Method", "Message"} );
Thread.Sleep (1000);
}
}

#endregion
}
}

********************************************************
 
C

ClayB [Syncfusion]

You can only interact access the DataGrid on the thread that created it. In
this case, as the new rows are being added to the DataTable, events are
being raised by the DataTable that the datagrid is listening to, and
responding to. This is a problem as the events are being raised on the
non-UI thread, and forcing the grid to respond to them.

One possible solution is to wrap the DataSource in a derived DataView. The
point of doing this is that in the derived class you can override the
methods that are handling the events fired by the DataView, and in the
handlers you can check to see whether you are using the datagrid's thread,
and if not, you can use Control.Invoke to call the method again on the
proper thread. Attached is a minimal sample illustrating how you might try
something like this.

Another option might be to use a third party grid that may handle such
threading issues in a more robust manner.

=================================
Clay Burch, .NET MVP

Visit www.syncfusion.com for the coolest tools

Venkata said:
I have a SystemData class (Singleton class extends the DataSet) which has
one Table (Trace: 4 Columns). I start a thread in its constructor which
keeps on adding data to the table (simulating Real-Time data).
I have a form (Form1) in my C# project which has a DataGrid (DataGrid1). I
have set the DataSource property of this grid to the "Trace" table created
above.
I can see the data being added to the grid instantaneously but after some
time the system hangs up and I see the following Stack Trace. It also hangs
up if I try to change the Column width in the grid. I have no clue whats
going on as I am not trying to set any tool tips.
********************Stack Trace***************************
system.windows.forms.dll!System.Windows.Forms.DataGridToolTip.CreateToolTipH
andle() + 0x1db bytes
system.windows.forms.dll!System.Windows.Forms.DataGrid.ResetToolTip() + 0x44 bytes
system.windows.forms.dll!System.Windows.Forms.DataGrid.OnLayout(System.Windo
ws.Forms.LayoutEventArgs levent = {System.Windows.Forms.LayoutEventArgs}) +
0xad bytessystem.windows.forms.dll!System.Windows.Forms.Control.PerformLayout(System.W
string said:
system.windows.forms.dll!System.Windows.Forms.Control.PerformLayout() + 0xf bytes
system.windows.forms.dll!System.Windows.Forms.DataGridColumnStyle.set_Width(
int value = 123) + 0x4f bytessystem.windows.forms.dll!System.Windows.Forms.DataGrid.ColResizeEnd(System.W
indows.Forms.MouseEventArgs e = {X=158 Y=26 Button=Left}) + 0x19f bytessystem.windows.forms.dll!System.Windows.Forms.DataGrid.OnMouseUp(System.Wind
ows.Forms.MouseEventArgs e = {X=158 Y=26 Button=Left}) + 0x7f bytessystem.windows.forms.dll!System.Windows.Forms.Control.WmMouseUp(System.Windo
ws.Forms.Message m = {System.Windows.Forms.Message},
System.Windows.Forms.MouseButtons button = Left, int clicks = 1) + 0x261
bytessystem.windows.forms.dll!System.Windows.Forms.Control.WndProc(System.Windows
..Forms.Message m = {System.Windows.Forms.Message}) + 0x49b bytessystem.windows.forms.dll!ControlNativeWindow.OnMessage(System.Windows.Forms.
Message m = {System.Windows.Forms.Message}) + 0x13 bytessystem.windows.forms.dll!ControlNativeWindow.WndProc(System.Windows.Forms.Me
ssage m = {System.Windows.Forms.Message}) + 0xda bytessystem.windows.forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallbac
k(int hWnd = 26871752, int msg = 514, int wparam = 0, int lparam = 1704094)
+ 0x3d bytessystem.windows.forms.dll!System.Windows.Forms.Application.ComponentManager.S
ystem.Windows.Forms.UnsafeNativeMethods+IMsoComponentManager.FPushMessageLoo
p(int dwComponentID = 1, int reason = -1, int pvLoopData = 0) + 0x349 bytes
system.windows.forms.dll!ThreadContext.RunMessageLoopInner(int reason
= -1, System.Windows.Forms.ApplicationContext context =
{System.Windows.Forms.ApplicationContext}) + 0x1f3 bytes
system.windows.forms.dll!ThreadContext.RunMessageLoop(int reason = -1,
System.Windows.Forms.ApplicationContext context =
{System.Windows.Forms.ApplicationContext}) + 0x50 bytessystem.windows.forms.dll!System.Windows.Forms.Application.Run(System.Windows
..Forms.Form mainForm = {Testing.Form1}) + 0x34 bytes
Testing.exe!Testing.Form1.Main() Line 122 C#

********************************************************
********************SystemData.cs**************************
using System;
using System.Data;
using System.Threading;
using System.Windows.Forms;

namespace Testing
{
public class SystemData : DataSet
{
#region Private Variables

private static SystemData m_instance = null;

#endregion

#region Public Constructor

private SystemData()
{
m_Write = new ManualResetEvent(true);

// Add Trace Table
DataTable dtTrace = new DataTable("Trace");

dtTrace.Columns.Add("Time Stamp", Type.GetType("System.String"));
dtTrace.Columns.Add("Module Name", Type.GetType("System.String"));
dtTrace.Columns.Add("Method Name", Type.GetType("System.String"));
dtTrace.Columns.Add("Message", Type.GetType("System.String"));

Tables.Add(dtTrace);

Thread m_SubscriptionThread = new Thread (new ThreadStart (FillData));
m_SubscriptionThread.Start();
}

#endregion

#region Public Methods

public static SystemData GetInstance()
{
if ( m_instance == null )
m_instance = new SystemData();

return m_instance;
}

#endregion

#region Private Methods

private void FillData()
{
while (true)
{
Tables["Trace"].Rows.Add ( new Object[] {DateTime.Now.ToString(),
"Module", "Method", "Message"} );
 
G

Guest

I did the following but still have the same problem. If you dont mind can you show me an example on how to do it.

I created the following derived class SystemDataView and set the DataSource property of the grid to this as follows:
this.dataGrid1.DataSource = new SystemDataView(SystemData.GetInstance().Tables["Trace"]);

*****************************************
public class SystemDataView: DataView
{
public SystemDataView(DataTable table)
{
base.Table = table;
ListChanged +=new System.ComponentModel.ListChangedEventHandler(SystemDataView_ListChanged);
}

private void SystemDataView_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e)
{
Console.WriteLine( "List Changed." );
}

*****************************************


ClayB said:
You can only interact access the DataGrid on the thread that created it. In
this case, as the new rows are being added to the DataTable, events are
being raised by the DataTable that the datagrid is listening to, and
responding to. This is a problem as the events are being raised on the
non-UI thread, and forcing the grid to respond to them.

One possible solution is to wrap the DataSource in a derived DataView. The
point of doing this is that in the derived class you can override the
methods that are handling the events fired by the DataView, and in the
handlers you can check to see whether you are using the datagrid's thread,
and if not, you can use Control.Invoke to call the method again on the
proper thread. Attached is a minimal sample illustrating how you might try
something like this.

Another option might be to use a third party grid that may handle such
threading issues in a more robust manner.

=================================
Clay Burch, .NET MVP

Visit www.syncfusion.com for the coolest tools

Venkata said:
I have a SystemData class (Singleton class extends the DataSet) which has
one Table (Trace: 4 Columns). I start a thread in its constructor which
keeps on adding data to the table (simulating Real-Time data).
I have a form (Form1) in my C# project which has a DataGrid (DataGrid1). I
have set the DataSource property of this grid to the "Trace" table created
above.
I can see the data being added to the grid instantaneously but after some
time the system hangs up and I see the following Stack Trace. It also hangs
up if I try to change the Column width in the grid. I have no clue whats
going on as I am not trying to set any tool tips.
********************Stack Trace***************************
system.windows.forms.dll!System.Windows.Forms.DataGridToolTip.CreateToolTipH
andle() + 0x1db bytes
system.windows.forms.dll!System.Windows.Forms.DataGrid.ResetToolTip() + 0x44 bytes
system.windows.forms.dll!System.Windows.Forms.DataGrid.OnLayout(System.Windo
ws.Forms.LayoutEventArgs levent = {System.Windows.Forms.LayoutEventArgs}) +
0xad bytessystem.windows.forms.dll!System.Windows.Forms.Control.PerformLayout(System.W
string said:
system.windows.forms.dll!System.Windows.Forms.Control.PerformLayout() + 0xf bytes
system.windows.forms.dll!System.Windows.Forms.DataGridColumnStyle.set_Width(
int value = 123) + 0x4f bytessystem.windows.forms.dll!System.Windows.Forms.DataGrid.ColResizeEnd(System.W
indows.Forms.MouseEventArgs e = {X=158 Y=26 Button=Left}) + 0x19f bytessystem.windows.forms.dll!System.Windows.Forms.DataGrid.OnMouseUp(System.Wind
ows.Forms.MouseEventArgs e = {X=158 Y=26 Button=Left}) + 0x7f bytessystem.windows.forms.dll!System.Windows.Forms.Control.WmMouseUp(System.Windo
ws.Forms.Message m = {System.Windows.Forms.Message},
System.Windows.Forms.MouseButtons button = Left, int clicks = 1) + 0x261
bytessystem.windows.forms.dll!System.Windows.Forms.Control.WndProc(System.Windows
..Forms.Message m = {System.Windows.Forms.Message}) + 0x49b bytessystem.windows.forms.dll!ControlNativeWindow.OnMessage(System.Windows.Forms.
Message m = {System.Windows.Forms.Message}) + 0x13 bytessystem.windows.forms.dll!ControlNativeWindow.WndProc(System.Windows.Forms.Me
ssage m = {System.Windows.Forms.Message}) + 0xda bytessystem.windows.forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallbac
k(int hWnd = 26871752, int msg = 514, int wparam = 0, int lparam = 1704094)
+ 0x3d bytessystem.windows.forms.dll!System.Windows.Forms.Application.ComponentManager.S
ystem.Windows.Forms.UnsafeNativeMethods+IMsoComponentManager.FPushMessageLoo
p(int dwComponentID = 1, int reason = -1, int pvLoopData = 0) + 0x349 bytes
system.windows.forms.dll!ThreadContext.RunMessageLoopInner(int reason
= -1, System.Windows.Forms.ApplicationContext context =
{System.Windows.Forms.ApplicationContext}) + 0x1f3 bytes
system.windows.forms.dll!ThreadContext.RunMessageLoop(int reason = -1,
System.Windows.Forms.ApplicationContext context =
{System.Windows.Forms.ApplicationContext}) + 0x50 bytessystem.windows.forms.dll!System.Windows.Forms.Application.Run(System.Windows
..Forms.Form mainForm = {Testing.Form1}) + 0x34 bytes
Testing.exe!Testing.Form1.Main() Line 122 C#

********************************************************
********************SystemData.cs**************************
using System;
using System.Data;
using System.Threading;
using System.Windows.Forms;

namespace Testing
{
public class SystemData : DataSet
{
#region Private Variables

private static SystemData m_instance = null;

#endregion

#region Public Constructor

private SystemData()
{
m_Write = new ManualResetEvent(true);

// Add Trace Table
DataTable dtTrace = new DataTable("Trace");

dtTrace.Columns.Add("Time Stamp", Type.GetType("System.String"));
dtTrace.Columns.Add("Module Name", Type.GetType("System.String"));
dtTrace.Columns.Add("Method Name", Type.GetType("System.String"));
dtTrace.Columns.Add("Message", Type.GetType("System.String"));

Tables.Add(dtTrace);

Thread m_SubscriptionThread = new Thread (new ThreadStart (FillData));
m_SubscriptionThread.Start();
}

#endregion

#region Public Methods

public static SystemData GetInstance()
{
if ( m_instance == null )
m_instance = new SystemData();

return m_instance;
}

#endregion

#region Private Methods

private void FillData()
{
while (true)
{
Tables["Trace"].Rows.Add ( new Object[] {DateTime.Now.ToString(),
"Module", "Method", "Message"} );
Thread.Sleep (1000);
}
}

#endregion
}
}

********************************************************
 
G

Guest

I did the following but still have the same problem. If you dont mind can you show me an example on how to do it.

I created the following derived class SystemDataView and set the DataSource property of the grid to this as follows:
this.dataGrid1.DataSource = new SystemDataView(SystemData.GetInstance().Tables["Trace"]);

*****************************************
public class SystemDataView: DataView
{
public SystemDataView(DataTable table)
{
base.Table = table;
ListChanged +=new System.ComponentModel.ListChangedEventHandler(SystemDataView_ListChanged);
}

private void SystemDataView_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e)
{
Console.WriteLine( "List Changed." );
}

*****************************************


ClayB said:
You can only interact access the DataGrid on the thread that created it. In
this case, as the new rows are being added to the DataTable, events are
being raised by the DataTable that the datagrid is listening to, and
responding to. This is a problem as the events are being raised on the
non-UI thread, and forcing the grid to respond to them.

One possible solution is to wrap the DataSource in a derived DataView. The
point of doing this is that in the derived class you can override the
methods that are handling the events fired by the DataView, and in the
handlers you can check to see whether you are using the datagrid's thread,
and if not, you can use Control.Invoke to call the method again on the
proper thread. Attached is a minimal sample illustrating how you might try
something like this.

Another option might be to use a third party grid that may handle such
threading issues in a more robust manner.

=================================
Clay Burch, .NET MVP

Visit www.syncfusion.com for the coolest tools

Venkata said:
I have a SystemData class (Singleton class extends the DataSet) which has
one Table (Trace: 4 Columns). I start a thread in its constructor which
keeps on adding data to the table (simulating Real-Time data).
I have a form (Form1) in my C# project which has a DataGrid (DataGrid1). I
have set the DataSource property of this grid to the "Trace" table created
above.
I can see the data being added to the grid instantaneously but after some
time the system hangs up and I see the following Stack Trace. It also hangs
up if I try to change the Column width in the grid. I have no clue whats
going on as I am not trying to set any tool tips.
********************Stack Trace***************************
system.windows.forms.dll!System.Windows.Forms.DataGridToolTip.CreateToolTipH
andle() + 0x1db bytes
system.windows.forms.dll!System.Windows.Forms.DataGrid.ResetToolTip() + 0x44 bytes
system.windows.forms.dll!System.Windows.Forms.DataGrid.OnLayout(System.Windo
ws.Forms.LayoutEventArgs levent = {System.Windows.Forms.LayoutEventArgs}) +
0xad bytessystem.windows.forms.dll!System.Windows.Forms.Control.PerformLayout(System.W
string said:
system.windows.forms.dll!System.Windows.Forms.Control.PerformLayout() + 0xf bytes
system.windows.forms.dll!System.Windows.Forms.DataGridColumnStyle.set_Width(
int value = 123) + 0x4f bytessystem.windows.forms.dll!System.Windows.Forms.DataGrid.ColResizeEnd(System.W
indows.Forms.MouseEventArgs e = {X=158 Y=26 Button=Left}) + 0x19f bytessystem.windows.forms.dll!System.Windows.Forms.DataGrid.OnMouseUp(System.Wind
ows.Forms.MouseEventArgs e = {X=158 Y=26 Button=Left}) + 0x7f bytessystem.windows.forms.dll!System.Windows.Forms.Control.WmMouseUp(System.Windo
ws.Forms.Message m = {System.Windows.Forms.Message},
System.Windows.Forms.MouseButtons button = Left, int clicks = 1) + 0x261
bytessystem.windows.forms.dll!System.Windows.Forms.Control.WndProc(System.Windows
..Forms.Message m = {System.Windows.Forms.Message}) + 0x49b bytessystem.windows.forms.dll!ControlNativeWindow.OnMessage(System.Windows.Forms.
Message m = {System.Windows.Forms.Message}) + 0x13 bytessystem.windows.forms.dll!ControlNativeWindow.WndProc(System.Windows.Forms.Me
ssage m = {System.Windows.Forms.Message}) + 0xda bytessystem.windows.forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallbac
k(int hWnd = 26871752, int msg = 514, int wparam = 0, int lparam = 1704094)
+ 0x3d bytessystem.windows.forms.dll!System.Windows.Forms.Application.ComponentManager.S
ystem.Windows.Forms.UnsafeNativeMethods+IMsoComponentManager.FPushMessageLoo
p(int dwComponentID = 1, int reason = -1, int pvLoopData = 0) + 0x349 bytes
system.windows.forms.dll!ThreadContext.RunMessageLoopInner(int reason
= -1, System.Windows.Forms.ApplicationContext context =
{System.Windows.Forms.ApplicationContext}) + 0x1f3 bytes
system.windows.forms.dll!ThreadContext.RunMessageLoop(int reason = -1,
System.Windows.Forms.ApplicationContext context =
{System.Windows.Forms.ApplicationContext}) + 0x50 bytessystem.windows.forms.dll!System.Windows.Forms.Application.Run(System.Windows
..Forms.Form mainForm = {Testing.Form1}) + 0x34 bytes
Testing.exe!Testing.Form1.Main() Line 122 C#

********************************************************
********************SystemData.cs**************************
using System;
using System.Data;
using System.Threading;
using System.Windows.Forms;

namespace Testing
{
public class SystemData : DataSet
{
#region Private Variables

private static SystemData m_instance = null;

#endregion

#region Public Constructor

private SystemData()
{
m_Write = new ManualResetEvent(true);

// Add Trace Table
DataTable dtTrace = new DataTable("Trace");

dtTrace.Columns.Add("Time Stamp", Type.GetType("System.String"));
dtTrace.Columns.Add("Module Name", Type.GetType("System.String"));
dtTrace.Columns.Add("Method Name", Type.GetType("System.String"));
dtTrace.Columns.Add("Message", Type.GetType("System.String"));

Tables.Add(dtTrace);

Thread m_SubscriptionThread = new Thread (new ThreadStart (FillData));
m_SubscriptionThread.Start();
}

#endregion

#region Public Methods

public static SystemData GetInstance()
{
if ( m_instance == null )
m_instance = new SystemData();

return m_instance;
}

#endregion

#region Private Methods

private void FillData()
{
while (true)
{
Tables["Trace"].Rows.Add ( new Object[] {DateTime.Now.ToString(),
"Module", "Method", "Message"} );
Thread.Sleep (1000);
}
}

#endregion
}
}

********************************************************
 
C

ClayB [Syncfusion]

I actually attached a sample project to my first response. Could you not
download it?

Below is the text of the form1.cs file in that project.

===============================
Clay Burch, .NET MVP

Visit www.syncfusion.com for the coolest tools


using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;

namespace DataGridThreadProblem
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.DataGrid dataGrid1;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.dataGrid1 = new System.Windows.Forms.DataGrid();
((System.ComponentModel.ISupportInitialize)(this.dataGrid1)).BeginInit();
this.SuspendLayout();
//
// dataGrid1
//
this.dataGrid1.Anchor =
((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.To
p | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.dataGrid1.DataMember = "";
this.dataGrid1.HeaderForeColor = System.Drawing.SystemColors.ControlText;
this.dataGrid1.Location = new System.Drawing.Point(16, 24);
this.dataGrid1.Name = "dataGrid1";
this.dataGrid1.Size = new System.Drawing.Size(320, 224);
this.dataGrid1.TabIndex = 0;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(352, 266);
this.Controls.Add(this.dataGrid1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
((System.ComponentModel.ISupportInitialize)(this.dataGrid1)).EndInit();
this.ResumeLayout(false);

}
#endregion

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void Form1_Load(object sender, System.EventArgs e)
{

MyDataView dv = new MyDataView(this.dataGrid1);
dv.Table = SystemData.GetInstance().Tables["Trace"];
this.dataGrid1.DataSource = dv;
}
}


public class MyDataView : DataView
{
DataGrid grid;

public MyDataView(DataGrid grid)
: base()
{
this.grid = grid;
}


private delegate void OnListChangedDelegate(ListChangedEventArgs e);
protected override void OnListChanged(ListChangedEventArgs e)
{
if(grid != null && grid.InvokeRequired)
{
grid.Invoke(new OnListChangedDelegate(OnListChanged), new object[]{e});
}
else
base.OnListChanged (e);
}

private delegate void IndexListChangedDelegate(object sender,
ListChangedEventArgs e);
protected override void IndexListChanged(object sender,
ListChangedEventArgs e)
{
if(grid != null && grid.InvokeRequired)
{
grid.Invoke(new IndexListChangedDelegate(IndexListChanged), new
object[]{sender, e});
}
else
base.IndexListChanged (sender, e);
}
}


public class SystemData : DataSet
{
#region Private Variables

private static SystemData m_instance = null;

#endregion

#region Public Constructor

private SystemData()
{
//m_Write = new ManualResetEvent(true);

// Add Trace Table
DataTable dtTrace = new DataTable("Trace");

dtTrace.Columns.Add("Time Stamp", Type.GetType("System.String"));
dtTrace.Columns.Add("Module Name", Type.GetType("System.String"));
dtTrace.Columns.Add("Method Name", Type.GetType("System.String"));
dtTrace.Columns.Add("Message", Type.GetType("System.String"));

Tables.Add(dtTrace);

Thread m_SubscriptionThread = new Thread (new ThreadStart (FillData));
m_SubscriptionThread.Start();
}

#endregion

#region Public Methods

public static SystemData GetInstance()
{
if ( m_instance == null )
m_instance = new SystemData();

return m_instance;
}

#endregion

#region Private Methods

private void FillData()
{
while (true)
{
Tables["Trace"].Rows.Add ( new Object[] {DateTime.Now.ToString(),
"Module", "Method", "Message"} );
Thread.Sleep (1000);
}
}

#endregion
}

}






Venkata said:
I did the following but still have the same problem. If you dont mind can
you show me an example on how to do it.
I created the following derived class SystemDataView and set the
DataSource property of the grid to this as follows:
this.dataGrid1.DataSource = new SystemDataView(SystemData.GetInstance().Tables["Trace"]);

*****************************************
public class SystemDataView: DataView
{
public SystemDataView(DataTable table)
{
base.Table = table;
ListChanged +=new System.ComponentModel.ListChangedEventHandler(SystemDataView_ListChanged);
}

private void SystemDataView_ListChanged(object sender,
System.ComponentModel.ListChangedEventArgs e)
{
Console.WriteLine( "List Changed." );
}

*****************************************


ClayB said:
You can only interact access the DataGrid on the thread that created it. In
this case, as the new rows are being added to the DataTable, events are
being raised by the DataTable that the datagrid is listening to, and
responding to. This is a problem as the events are being raised on the
non-UI thread, and forcing the grid to respond to them.

One possible solution is to wrap the DataSource in a derived DataView. The
point of doing this is that in the derived class you can override the
methods that are handling the events fired by the DataView, and in the
handlers you can check to see whether you are using the datagrid's thread,
and if not, you can use Control.Invoke to call the method again on the
proper thread. Attached is a minimal sample illustrating how you might try
something like this.

Another option might be to use a third party grid that may handle such
threading issues in a more robust manner.

=================================
Clay Burch, .NET MVP

Visit www.syncfusion.com for the coolest tools

Venkata said:
I have a SystemData class (Singleton class extends the DataSet) which
has
one Table (Trace: 4 Columns). I start a thread in its constructor which
keeps on adding data to the table (simulating Real-Time data).
I have a form (Form1) in my C# project which has a DataGrid
(DataGrid1). I
have set the DataSource property of this grid to the "Trace" table created
above.
I can see the data being added to the grid instantaneously but after
some
time the system hangs up and I see the following Stack Trace. It also hangs
up if I try to change the Column width in the grid. I have no clue whats
going on as I am not trying to set any tool tips.
********************Stack Trace***************************
system.windows.forms.dll!System.Windows.Forms.DataGridToolTip.CreateToolTipH
andle() + 0x1db bytes system.windows.forms.dll!System.Windows.Forms.DataGrid.ResetToolTip() +
0x44 bytes system.windows.forms.dll!System.Windows.Forms.DataGrid.OnLayout(System.Windo
ws.Forms.LayoutEventArgs levent = {System.Windows.Forms.LayoutEventArgs}) +
0xad bytes system.windows.forms.dll!System.Windows.Forms.Control.PerformLayout(System.W
system.windows.forms.dll!System.Windows.Forms.Control.PerformLayout() +
0xf bytes system.windows.forms.dll!System.Windows.Forms.DataGridColumnStyle.set_Width(
int value = 123) + 0x4f bytes system.windows.forms.dll!System.Windows.Forms.DataGrid.ColResizeEnd(System.W
indows.Forms.MouseEventArgs e = {X=158 Y=26 Button=Left}) + 0x19f bytes system.windows.forms.dll!System.Windows.Forms.DataGrid.OnMouseUp(System.Wind
ows.Forms.MouseEventArgs e = {X=158 Y=26 Button=Left}) + 0x7f bytes system.windows.forms.dll!System.Windows.Forms.Control.WmMouseUp(System.Windo
ws.Forms.Message m = {System.Windows.Forms.Message},
System.Windows.Forms.MouseButtons button = Left, int clicks = 1) + 0x261
bytes system.windows.forms.dll!System.Windows.Forms.Control.WndProc(System.Windows
..Forms.Message m = {System.Windows.Forms.Message}) + 0x49b bytes system.windows.forms.dll!ControlNativeWindow.OnMessage(System.Windows.Forms.
Message m = {System.Windows.Forms.Message}) + 0x13 bytes system.windows.forms.dll!ControlNativeWindow.WndProc(System.Windows.Forms.Me
ssage m = {System.Windows.Forms.Message}) + 0xda bytes system.windows.forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallbac
k(int hWnd = 26871752, int msg = 514, int wparam = 0, int lparam = 1704094)
+ 0x3d bytes system.windows.forms.dll!System.Windows.Forms.Application.ComponentManager.S
ystem.Windows.Forms.UnsafeNativeMethods+IMsoComponentManager.FPushMessageLoo
p(int dwComponentID = 1, int reason = -1, int pvLoopData = 0) + 0x349 bytes
system.windows.forms.dll!ThreadContext.RunMessageLoopInner(int
reason
= -1, System.Windows.Forms.ApplicationContext context =
{System.Windows.Forms.ApplicationContext}) + 0x1f3 bytes
system.windows.forms.dll!ThreadContext.RunMessageLoop(int reason
= -1,
System.Windows.Forms.ApplicationContext context =
{System.Windows.Forms.ApplicationContext}) + 0x50 bytes system.windows.forms.dll!System.Windows.Forms.Application.Run(System.Windows
..Forms.Form mainForm = {Testing.Form1}) + 0x34 bytes
Testing.exe!Testing.Form1.Main() Line 122 C#

********************************************************
********************SystemData.cs**************************
using System;
using System.Data;
using System.Threading;
using System.Windows.Forms;

namespace Testing
{
public class SystemData : DataSet
{
#region Private Variables

private static SystemData m_instance = null;

#endregion

#region Public Constructor

private SystemData()
{
m_Write = new ManualResetEvent(true);

// Add Trace Table
DataTable dtTrace = new DataTable("Trace");

dtTrace.Columns.Add("Time Stamp", Type.GetType("System.String"));
dtTrace.Columns.Add("Module Name", Type.GetType("System.String"));
dtTrace.Columns.Add("Method Name", Type.GetType("System.String"));
dtTrace.Columns.Add("Message", Type.GetType("System.String"));

Tables.Add(dtTrace);

Thread m_SubscriptionThread = new Thread (new ThreadStart (FillData));
m_SubscriptionThread.Start();
}

#endregion

#region Public Methods

public static SystemData GetInstance()
{
if ( m_instance == null )
m_instance = new SystemData();

return m_instance;
}

#endregion

#region Private Methods

private void FillData()
{
while (true)
{
Tables["Trace"].Rows.Add ( new Object[] {DateTime.Now.ToString(),
"Module", "Method", "Message"} );
Thread.Sleep (1000);
}
}

#endregion
}
}

********************************************************
 
G

Guest

It looks like my problems never go away.

I added a Child Table to the original table which is alo being updated real-time. I added a relation so that I can browse the child table. I was able to do this successfully. Unfortunately when I click the Navigate Back button it is crashing with the same problem again.

Source code:
****************SystemData.cs***********************
using System;
using System.Collections;
using System.Data;
using System.Threading;
using System.Windows.Forms;

namespace Testing
{
public class SystemData : DataSet
{
public delegate void DelegateTrace();

#region Private Variables

private static SystemData m_instance = null;

#endregion

#region Public Constructor

private SystemData()
{
// Add Trace Table
DataTable dtTrace = new DataTable("Trace");

dtTrace.Columns.Add("Time Stamp", Type.GetType("System.String"));
dtTrace.Columns.Add("Module Name", Type.GetType("System.String"));
dtTrace.Columns.Add("Method Name", Type.GetType("System.String"));
dtTrace.Columns.Add("Message", Type.GetType("System.String"));

Tables.Add(dtTrace);

Tables["Trace"].RowChanged +=new DataRowChangeEventHandler(SystemData_RowChanged);

// Add Trace Table
DataTable dtTraceChild = new DataTable("TraceChild");

dtTraceChild.Columns.Add("Time Stamp", Type.GetType("System.String"));
dtTraceChild.Columns.Add("Module Name", Type.GetType("System.String"));
dtTraceChild.Columns.Add("Method Name", Type.GetType("System.String"));
dtTraceChild.Columns.Add("Message", Type.GetType("System.String"));

Tables.Add(dtTraceChild);

Relations.Add( "Trace_Child",
Tables[0].Columns["Time Stamp"],
Tables[1].Columns["Time Stamp"] );

Thread m_SubscriptionThread = new Thread (new ThreadStart (FillData));
m_SubscriptionThread.Start();
}

#endregion

#region Public Methods

public static SystemData GetInstance()
{
if ( m_instance == null )
m_instance = new SystemData();

return m_instance;
}

#endregion

#region Private Methods

private void FillData()
{
Random r = new Random();
string sTimeStamp;

while (true)
{
sTimeStamp = DateTime.Now.ToString();
Tables[0].Rows.Add ( new Object[] {sTimeStamp, "Module", "Method", "Message"} );
for (int i=0; i<10; i++)
{
Tables[1].Rows.Add ( new Object[] {sTimeStamp, "Module", "Method", "Message"} );
Thread.Sleep (1000);
}
Thread.Sleep (/*r.Next(10) * */1000);
}
}

private void SystemData_RowChanged(object sender, DataRowChangeEventArgs e)
{
Console.WriteLine( "DataSet: " + e.Row.ItemArray[0].ToString() );
}

#endregion
}
}

***************************************

The following is the stack trace:

*****************************************************
system.windows.forms.dll!System.Windows.Forms.DataGridToolTip.CreateToolTipHandle() + 0x1db bytes
system.windows.forms.dll!System.Windows.Forms.DataGrid.ResetToolTip() + 0x44 bytes
system.windows.forms.dll!System.Windows.Forms.DataGrid.OnLayout(System.Windows.Forms.LayoutEventArgs levent = {System.Windows.Forms.LayoutEventArgs}) + 0xad bytes
system.windows.forms.dll!System.Windows.Forms.Control.PerformLayout(System.Windows.Forms.Control affectedControl = {System.Windows.Forms.DataGridTextBox}, string affectedProperty = "Parent") + 0x7c bytes
system.windows.forms.dll!System.Windows.Forms.Control.ControlCollection.Remove(System.Windows.Forms.Control value = {System.Windows.Forms.DataGridTextBox}) + 0xdb bytes
system.windows.forms.dll!System.Windows.Forms.DataGridTextBoxColumn.ReleaseHostedControl() + 0x38 bytes
system.windows.forms.dll!System.Windows.Forms.GridColumnStylesCollection.ResetDefaultColumnCollection() + 0x23 bytes
system.windows.forms.dll!System.Windows.Forms.DataGrid.Set_ListManager(System.Object newDataSource = {OpenScapeSDKApplications.MyDataView}, string newDataMember = "", bool force = true, bool forceColumnCreation = false) + 0x2aa bytes
system.windows.forms.dll!System.Windows.Forms.DataGridState.PullState(System.Windows.Forms.DataGrid dataGrid = {OpenScapeSDKApplications.MyDataGrid}, bool createColumn = false) + 0x21 bytes
system.windows.forms.dll!System.Windows.Forms.DataGrid.NavigateBack() + 0xfe bytes
system.windows.forms.dll!System.Windows.Forms.DataGrid.OnBackButtonClicked(System.Object sender = {System.Windows.Forms.DataGridCaption}, System.EventArgs e = {System.EventArgs}) + 0x14 bytes
system.windows.forms.dll!System.Windows.Forms.DataGridCaption.OnBackwardClicked(System.EventArgs e = {System.EventArgs}) + 0x53 bytes
system.windows.forms.dll!System.Windows.Forms.DataGridCaption.MouseUp(int x = 705, int y = 7) + 0x80 bytes
system.windows.forms.dll!System.Windows.Forms.DataGrid.OnMouseUp(System.Windows.Forms.MouseEventArgs e = {X=705 Y=7 Button=Left}) + 0x140 bytes
system.windows.forms.dll!System.Windows.Forms.Control.WmMouseUp(System.Windows.Forms.Message m = {System.Windows.Forms.Message}, System.Windows.Forms.MouseButtons button = Left, int clicks = 1) + 0x261 bytes
system.windows.forms.dll!System.Windows.Forms.Control.WndProc(System.Windows.Forms.Message m = {System.Windows.Forms.Message}) + 0x49b bytes
system.windows.forms.dll!ControlNativeWindow.OnMessage(System.Windows.Forms.Message m = {System.Windows.Forms.Message}) + 0x13 bytes
system.windows.forms.dll!ControlNativeWindow.WndProc(System.Windows.Forms.Message m = {System.Windows.Forms.Message}) + 0xda bytes
system.windows.forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(int hWnd = 197892, int msg = 514, int wparam = 0, int lparam = 459457) + 0x3d bytes
system.windows.forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods+IMsoComponentManager.FPushMessageLoop(int dwComponentID = 1, int reason = -1, int pvLoopData = 0) + 0x349 bytes
system.windows.forms.dll!ThreadContext.RunMessageLoopInner(int reason = -1, System.Windows.Forms.ApplicationContext context = {System.Windows.Forms.ApplicationContext}) + 0x1f3 bytes
system.windows.forms.dll!ThreadContext.RunMessageLoop(int reason = -1, System.Windows.Forms.ApplicationContext context = {System.Windows.Forms.ApplicationContext}) + 0x50 bytes
system.windows.forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.Form mainForm = {OpenScapeSDKApplications.Background}) + 0x34 bytes
Statistics.exe!OpenScapeSDKApplications.Background.Main() Line 213 + 0x1c bytes C#
*****************************************************

I implemented the event OnBackButtonClicked() for the grid and invoked the NavigateBack() function from there but the code never got executed. I am not sure which methods/events should I override in this case.


Also,
To avoid the above problem I displayed the Parent and Child grids on the same form and used a DataviewManager to display the Parent and Child data. I did create a subclass from the DataViewManager and also did override the OnListChanged method but I was still having the same problem. I am not sure what to do here.


Can you please help me out in these issues.

Thank You,
Venkata.
 
G

Guest

It worked. I just followed the same instruction you gave for the DataView.
I created a subclass for the DataGrid and did a overrite the OnLayout method.

But I am still confused on how will anyone be able to identify which control to subclass and which method to overrite?

Any suggestions?

Thanks,
venkata.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top