Can't add data to DataSet from non-creating thread?

J

John

Hi,

My app receives data via an async socket. I need to put this data into a
DataSet and display it via a DataGrid.

If I add the data to the dataset when it arrives using the async created
thread, my app crashes with a NullException inside Application.Run().

If I disconnect the DataSet from the DataGrid (dataGrid.DataSouce = null),
then the app does NOT crash. It only crashes when I'm trying to display the
data that I'm adding to the DataGrid.

So what's the best way to solve this problem? How do you get data into a
DataSet via the non-creating thread?

I built a demo app below that demonstrates the problem which is listed
below.

THANKS!
John



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

namespace DataGrid
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class DG : System.Windows.Forms.Form
{
Random random = new Random();
bool running = true;

private System.Windows.Forms.DataGrid dataGrid;
private DataGrid.MyDataset myDataset;
private System.Windows.Forms.Timer timer;
private System.Windows.Forms.CheckBox checkBox;
private System.ComponentModel.IContainer components;

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

dataGrid.DataSource = myDataset;

ThreadStart threadStart = new ThreadStart(listenThread);
Thread thread = new Thread(threadStart);
thread.IsBackground = true;
thread.Start();
}

private void listenThread()
{
while ( running )
{
// How do I add data to myDataset from this thread?

// If I add data to myDataset from this thread, while
// myDataset is "connected" to the datagrid, then the
// app will crash with a NullException

// How do I use the "main" thread to add data to myDataset?

// myDataset.MyTable.AddMyTableRow(DateTime.Now, random.Next());


Thread.Sleep(200);
}
}

/// <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.components = new System.ComponentModel.Container();
this.dataGrid = new System.Windows.Forms.DataGrid();
this.myDataset = new DataGrid.MyDataset();
this.timer = new System.Windows.Forms.Timer(this.components);
this.checkBox = new System.Windows.Forms.CheckBox();
((System.ComponentModel.ISupportInitialize)(this.dataGrid)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.myDataset)).BeginInit();
this.SuspendLayout();
//
// dataGrid
//
this.dataGrid.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.dataGrid.DataMember = "";
this.dataGrid.HeaderForeColor = System.Drawing.SystemColors.ControlText;
this.dataGrid.Location = new System.Drawing.Point(8, 48);
this.dataGrid.Name = "dataGrid";
this.dataGrid.Size = new System.Drawing.Size(280, 216);
this.dataGrid.TabIndex = 0;
//
// myDataset
//
this.myDataset.DataSetName = "MyDataset";
this.myDataset.Locale = new System.Globalization.CultureInfo("en-US");
//
// timer
//
this.timer.Tick += new System.EventHandler(this.timer_Tick);
//
// checkBox
//
this.checkBox.Location = new System.Drawing.Point(8, 8);
this.checkBox.Name = "checkBox";
this.checkBox.TabIndex = 1;
this.checkBox.Text = "Timer Enabled";
this.checkBox.CheckedChanged += new
System.EventHandler(this.checkBox_CheckedChanged);
//
// DG
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(296, 271);
this.Controls.Add(this.checkBox);
this.Controls.Add(this.dataGrid);
this.Name = "DG";
this.Text = "DataGrid Test";
((System.ComponentModel.ISupportInitialize)(this.dataGrid)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.myDataset)).EndInit();
this.ResumeLayout(false);

}
#endregion

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

private void checkBox_CheckedChanged(object sender, System.EventArgs e)
{
timer.Enabled = checkBox.Checked;
}

private void timer_Tick(object sender, System.EventArgs e)
{
// NOTE: THIS WORKS

// Console.WriteLine("Fire");

// myDataset.MyTable.AddMyTableRow(DateTime.Now, random.Next());
}
}
}
 
K

Kevin Yu [MSFT]

Hi John,

I've written a short sample for you. It works well on my computer.

private System.Data.DataRow dr;

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

dataGrid.DataSource = myDataset;
dr = null;

ThreadStart threadStart = new ThreadStart(listenThread);
Thread thread = new Thread(threadStart);
thread.IsBackground = true;
thread.Start();
}

private void listenThread() //Generate new data
{
while ( running )
{
lock(this)
{
if(this.dr == null)
{
dr = myDataset.MyTable.NewMyTableRow();
dr[0] = DateTime.Now;
dr[1] = random.Next();
}
}

this.Invoke(new MethodInvoker(AddData)); //Post a message to the main
thread.
Thread.Sleep(200);
}
}

private void AddData() //Receive message from another thread and add row
to the dataset
{ //This one works in the main thread.
lock(this)
{
if(this.dr != null)
this.myDataset.MyTable.Rows.Add(dr);
this.dr = null;
}
}


Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."

--------------------
| From: "John" <[email protected]>
| Subject: Can't add data to DataSet from non-creating thread?
| Date: Tue, 28 Oct 2003 11:06:29 -0500
| Lines: 185
| X-Priority: 3
| X-MSMail-Priority: Normal
| X-Newsreader: Microsoft Outlook Express 6.00.2800.1158
| X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165
| Message-ID: <[email protected]>
| Newsgroups: microsoft.public.dotnet.framework.adonet
| NNTP-Posting-Host: cosiapat1.net.americas.agilent.com 192.25.240.225
| Path: cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!TK2MSFTNGP09.phx.gbl
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.framework.adonet:64749
| X-Tomcat-NG: microsoft.public.dotnet.framework.adonet
|
| Hi,
|
| My app receives data via an async socket. I need to put this data into a
| DataSet and display it via a DataGrid.
|
| If I add the data to the dataset when it arrives using the async created
| thread, my app crashes with a NullException inside Application.Run().
|
| If I disconnect the DataSet from the DataGrid (dataGrid.DataSouce = null),
| then the app does NOT crash. It only crashes when I'm trying to display
the
| data that I'm adding to the DataGrid.
|
| So what's the best way to solve this problem? How do you get data into a
| DataSet via the non-creating thread?
|
| I built a demo app below that demonstrates the problem which is listed
| below.
|
| THANKS!
| John
|
|
|
| using System;
| using System.Drawing;
| using System.Collections;
| using System.ComponentModel;
| using System.Windows.Forms;
| using System.Data;
| using System.Threading;
|
| namespace DataGrid
| {
| /// <summary>
| /// Summary description for Form1.
| /// </summary>
| public class DG : System.Windows.Forms.Form
| {
| Random random = new Random();
| bool running = true;
|
| private System.Windows.Forms.DataGrid dataGrid;
| private DataGrid.MyDataset myDataset;
| private System.Windows.Forms.Timer timer;
| private System.Windows.Forms.CheckBox checkBox;
| private System.ComponentModel.IContainer components;
|
| public DG()
| {
| //
| // Required for Windows Form Designer support
| //
| InitializeComponent();
|
| dataGrid.DataSource = myDataset;
|
| ThreadStart threadStart = new ThreadStart(listenThread);
| Thread thread = new Thread(threadStart);
| thread.IsBackground = true;
| thread.Start();
| }
|
| private void listenThread()
| {
| while ( running )
| {
| // How do I add data to myDataset from this thread?
|
| // If I add data to myDataset from this thread, while
| // myDataset is "connected" to the datagrid, then the
| // app will crash with a NullException
|
| // How do I use the "main" thread to add data to myDataset?
|
| // myDataset.MyTable.AddMyTableRow(DateTime.Now, random.Next());
|
|
| Thread.Sleep(200);
| }
| }
|
| /// <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.components = new System.ComponentModel.Container();
| this.dataGrid = new System.Windows.Forms.DataGrid();
| this.myDataset = new DataGrid.MyDataset();
| this.timer = new System.Windows.Forms.Timer(this.components);
| this.checkBox = new System.Windows.Forms.CheckBox();
|
((System.ComponentModel.ISupportInitialize)(this.dataGrid)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.myDataset)).BeginInit();
| this.SuspendLayout();
| //
| // dataGrid
| //
| this.dataGrid.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.dataGrid.DataMember = "";
| this.dataGrid.HeaderForeColor =
System.Drawing.SystemColors.ControlText;
| this.dataGrid.Location = new System.Drawing.Point(8, 48);
| this.dataGrid.Name = "dataGrid";
| this.dataGrid.Size = new System.Drawing.Size(280, 216);
| this.dataGrid.TabIndex = 0;
| //
| // myDataset
| //
| this.myDataset.DataSetName = "MyDataset";
| this.myDataset.Locale = new System.Globalization.CultureInfo("en-US");
| //
| // timer
| //
| this.timer.Tick += new System.EventHandler(this.timer_Tick);
| //
| // checkBox
| //
| this.checkBox.Location = new System.Drawing.Point(8, 8);
| this.checkBox.Name = "checkBox";
| this.checkBox.TabIndex = 1;
| this.checkBox.Text = "Timer Enabled";
| this.checkBox.CheckedChanged += new
| System.EventHandler(this.checkBox_CheckedChanged);
| //
| // DG
| //
| this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
| this.ClientSize = new System.Drawing.Size(296, 271);
| this.Controls.Add(this.checkBox);
| this.Controls.Add(this.dataGrid);
| this.Name = "DG";
| this.Text = "DataGrid Test";
| ((System.ComponentModel.ISupportInitialize)(this.dataGrid)).EndInit();
| ((System.ComponentModel.ISupportInitialize)(this.myDataset)).EndInit();
| this.ResumeLayout(false);
|
| }
| #endregion
|
| /// <summary>
| /// The main entry point for the application.
| /// </summary>
| [STAThread]
| static void Main()
| {
| Application.Run(new DG());
| }
|
| private void checkBox_CheckedChanged(object sender, System.EventArgs e)
| {
| timer.Enabled = checkBox.Checked;
| }
|
| private void timer_Tick(object sender, System.EventArgs e)
| {
| // NOTE: THIS WORKS
|
| // Console.WriteLine("Fire");
|
| // myDataset.MyTable.AddMyTableRow(DateTime.Now, random.Next());
| }
| }
| }
|
|
|
 

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