PC Review


Reply
Thread Tools Rate Thread

C#, Threads, Events, and DataGrids/DataSets

 
 
=?Utf-8?B?RGVubmlzIE93ZW5z?=
Guest
Posts: n/a
 
      24th Feb 2004
I am trying to run a thread off of a form, and every once in a while the thread will raise an event for the form to read. When the form gets the event, the form will place the event into a dataset and display it on a datagrid that is on the form. The problem is that the thread will slowly take over all of the processor time. After about 8 events, the form will not even respond anymore. Here is the guts of my test code

// Class and event for Threa
using System

namespace ThreadTestStuf

public delegate void TestEventHandler(object sender,int count)
public class TestThread
public event TestEventHandler TestEvent
public bool stopRunning = false
public TestThread(
{
public void RunningThread()
int xyz = 0
while (!stopRunning)
xyz += 1
Console.WriteLine("Count: " + xyz.ToString())
if (xyz % 1000 == 0)
TestEvent(this,xyz)







// Form that call the test threa
// Data set only has (int count) and (string desc) in i

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

namespace ThreadTes

public class ThreadTestForm : System.Windows.Forms.For

private ThreadTest.TestSet testSet1
private System.Windows.Forms.DataGrid TestDG
private System.Windows.Forms.Button StartThreadButton
private Thread localThread
private TestThread localTestThread

private System.ComponentModel.Container components = null

public ThreadTestForm(

InitializeComponent()


protected override void Dispose( bool disposing
{
localTestThread.stopRunning = true
localThread.Abort()
if( disposing

if (components != null)

components.Dispose()


base.Dispose( disposing )


private void InitializeComponent(

this.testSet1 = new ThreadTest.TestSet()
this.TestDG = new System.Windows.Forms.DataGrid()
this.StartThreadButton = new System.Windows.Forms.Button()
((System.ComponentModel.ISupportInitialize)(this.testSet1)).BeginInit()
((System.ComponentModel.ISupportInitialize)(this.TestDG)).BeginInit()
this.SuspendLayout()
//
// testSet
//
this.testSet1.DataSetName = "TestSet"
this.testSet1.Locale = new System.Globalization.CultureInfo("en-US")
//
// TestD
//
this.TestDG.DataMember = ""
this.TestDG.DataSource = this.testSet1.TestTable
this.TestDG.HeaderForeColor = System.Drawing.SystemColors.ControlText
this.TestDG.Location = new System.Drawing.Point(16, 24)
this.TestDG.Name = "TestDG"
this.TestDG.Size = new System.Drawing.Size(320, 144)
this.TestDG.TabIndex = 0
//
// StartThreadButto
//
this.StartThreadButton.Location = new System.Drawing.Point(224, 184)
this.StartThreadButton.Name = "StartThreadButton"
this.StartThreadButton.Size = new System.Drawing.Size(120, 32)
this.StartThreadButton.TabIndex = 1
this.StartThreadButton.Text = "Start Thread"
this.StartThreadButton.Click += new System.EventHandler(this.StartThreadButton_Click)
//
// ThreadTestFor
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13)
this.ClientSize = new System.Drawing.Size(376, 253)
this.Controls.Add(this.StartThreadButton)
this.Controls.Add(this.TestDG)
this.Name = "ThreadTestForm"
this.Text = "Thread Test Form"
((System.ComponentModel.ISupportInitialize)(this.testSet1)).EndInit()
((System.ComponentModel.ISupportInitialize)(this.TestDG)).EndInit()
this.ResumeLayout(false)


#endregio

/// <summary
/// The main entry point for the application
/// </summary
[STAThread
static void Main()

Application.Run(new ThreadTestForm())

private void EventHappend(object sender, int count

localThread.Interrupt()
testSet1.TestTable.AddTestTableRow(count,"Hello There")
// MessageBox.Show(localThread.ThreadState.ToString())


private void StartThreadButton_Click(object sender, System.EventArgs e
{
localTestThread = new TestThread();
localTestThread.TestEvent += new TestEventHandler(this.EventHappend);
localThread = new Thread(new ThreadStart(localTestThread.RunningThread));
localThread.Start();
localThread.IsBackground = true;

}
}
}

Can anyone help?
Thanks,
Dennis Owens
 
Reply With Quote
 
 
 
 
Jon Skeet [C# MVP]
Guest
Posts: n/a
 
      24th Feb 2004
Dennis Owens <(E-Mail Removed)> wrote:
> I am trying to run a thread off of a form, and every once in a while
> the thread will raise an event for the form to read. When the form
> gets the event, the form will place the event into a dataset and
> display it on a datagrid that is on the form. The problem is that the
> thread will slowly take over all of the processor time. After about 8
> events, the form will not even respond anymore. Here is the guts of my
> test code.


I'm not surprised - you've got 8 threads in a tight loop. That's bound
to take over the processor! However, you've got a few other nasties
going on...

Firstly, you're accessing stopRunning in a non-thread-safe way. You
should either declare it as being volatile, or wrap any access to it in
a lock.

Secondly, you should never update the GUI from a non-UI thread, as you
currently are doing. You should use Control.Invoke to invoke a delegate
on the UI thread.

Thirdly, why are you calling localThread.Interrupt() from your event?
At that time, you're actually running *in* the thread you're trying to
interrupt!

--
Jon Skeet - <(E-Mail Removed)>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
 
Reply With Quote
 
=?Utf-8?B?RGVubmlzIE93ZW5z?=
Guest
Posts: n/a
 
      24th Feb 2004
The interrrupt was just a wild guess to try and stop it from sucking up all the processor time. I forgot I left it in there. The only line in that method should be the adding of the row in the dataset. As for your second thing, is this what is causing the thread to take over. Well I will lookup Control.Invoke and see if I can figure it out. I still don't see the eight threads, just the form and the test thread

Thanks Dennis Owen

 
Reply With Quote
 
Valery Pryamikov
Guest
Posts: n/a
 
      24th Feb 2004
Hi,
stopRunning doesn't need to be declared volatile and it should not be used
with locks.
Native integer assignment is atomic operation as well as native integer
promotion (even so the last doesn't even count).
No compiler would optimize away loading of cycle variable when there is
nontrivial cycle body (like non-inlined method calls inside of cycle).
And you don't need release/acquire semantic for single variable with atomic
assignment.
Using LOCK for accessing it would be unnecessary performance hit if not to
say a mistake.

I suppose that he misinterpreted meaning of Thread.Interrupt, and you are
correct with the rest of your comments.

-Valery.

See my blog at:
http://www.harper.no/valery

"Jon Skeet [C# MVP]" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Dennis Owens <(E-Mail Removed)> wrote:
> > I am trying to run a thread off of a form, and every once in a while
> > the thread will raise an event for the form to read. When the form
> > gets the event, the form will place the event into a dataset and
> > display it on a datagrid that is on the form. The problem is that the
> > thread will slowly take over all of the processor time. After about 8
> > events, the form will not even respond anymore. Here is the guts of my
> > test code.

>
> I'm not surprised - you've got 8 threads in a tight loop. That's bound
> to take over the processor! However, you've got a few other nasties
> going on...
>
> Firstly, you're accessing stopRunning in a non-thread-safe way. You
> should either declare it as being volatile, or wrap any access to it in
> a lock.
>
> Secondly, you should never update the GUI from a non-UI thread, as you
> currently are doing. You should use Control.Invoke to invoke a delegate
> on the UI thread.
>
> Thirdly, why are you calling localThread.Interrupt() from your event?
> At that time, you're actually running *in* the thread you're trying to
> interrupt!
>
> --
> Jon Skeet - <(E-Mail Removed)>
> http://www.pobox.com/~skeet
> If replying to the group, please do not mail me too



 
Reply With Quote
 
Valery Pryamikov
Guest
Posts: n/a
 
      24th Feb 2004
You have tight loop inside your thread method - of course it eats all
processor resources!
And btw, setting thread as background doesn't affect thread
priority/scheduling. it only says that .Net process can terminate even so
there are some background threads still running (I just think that you got
it wrong too)

and do as Jon said to you - use Invoke when you update controls from non-UI
threads.

-Valery

See my blog at:
http://www.harper.no/valery


"Dennis Owens" <(E-Mail Removed)> wrote in message
news:00D069B1-4B67-4DCA-8C23-(E-Mail Removed)...
> The interrrupt was just a wild guess to try and stop it from sucking up

all the processor time. I forgot I left it in there. The only line in that
method should be the adding of the row in the dataset. As for your second
thing, is this what is causing the thread to take over. Well I will lookup
Control.Invoke and see if I can figure it out. I still don't see the eight
threads, just the form and the test thread?
>
> Thanks Dennis Owens
>



 
Reply With Quote
 
=?Utf-8?B?RGVubmlzIE93ZW5z?=
Guest
Posts: n/a
 
      24th Feb 2004
Ok here is a simple question, how should this simple example be written

Thanks Dennis Owens
 
Reply With Quote
 
Valery Pryamikov
Guest
Posts: n/a
 
      24th Feb 2004
btw (for avoiding being misinterpreted) I didn't say that using bool flag as
thread event is good design :-). He should use kernel object like event for
signaling exit.

-Valery.

See my blog at:
http://www.harper.no/valery

"Valery Pryamikov" <(E-Mail Removed)> wrote in message
news:%23yddtux%(E-Mail Removed)...
> Hi,
> stopRunning doesn't need to be declared volatile and it should not be used
> with locks.
> Native integer assignment is atomic operation as well as native integer
> promotion (even so the last doesn't even count).
> No compiler would optimize away loading of cycle variable when there is
> nontrivial cycle body (like non-inlined method calls inside of cycle).
> And you don't need release/acquire semantic for single variable with

atomic
> assignment.
> Using LOCK for accessing it would be unnecessary performance hit if not to
> say a mistake.
>
> I suppose that he misinterpreted meaning of Thread.Interrupt, and you are
> correct with the rest of your comments.
>
> -Valery.
>
> See my blog at:
> http://www.harper.no/valery
>
> "Jon Skeet [C# MVP]" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
> > Dennis Owens <(E-Mail Removed)> wrote:
> > > I am trying to run a thread off of a form, and every once in a while
> > > the thread will raise an event for the form to read. When the form
> > > gets the event, the form will place the event into a dataset and
> > > display it on a datagrid that is on the form. The problem is that the
> > > thread will slowly take over all of the processor time. After about 8
> > > events, the form will not even respond anymore. Here is the guts of my
> > > test code.

> >
> > I'm not surprised - you've got 8 threads in a tight loop. That's bound
> > to take over the processor! However, you've got a few other nasties
> > going on...
> >
> > Firstly, you're accessing stopRunning in a non-thread-safe way. You
> > should either declare it as being volatile, or wrap any access to it in
> > a lock.
> >
> > Secondly, you should never update the GUI from a non-UI thread, as you
> > currently are doing. You should use Control.Invoke to invoke a delegate
> > on the UI thread.
> >
> > Thirdly, why are you calling localThread.Interrupt() from your event?
> > At that time, you're actually running *in* the thread you're trying to
> > interrupt!
> >
> > --
> > Jon Skeet - <(E-Mail Removed)>
> > http://www.pobox.com/~skeet
> > If replying to the group, please do not mail me too

>
>



 
Reply With Quote
 
Jon Skeet [C# MVP]
Guest
Posts: n/a
 
      24th Feb 2004
Valery Pryamikov <(E-Mail Removed)> wrote:
> stopRunning doesn't need to be declared volatile and it should not be used
> with locks.
> Native integer assignment is atomic operation as well as native integer
> promotion (even so the last doesn't even count).


Being atomic has nothing to do with it. The memory model does not
guarantee that the running thread will *ever* see writes from another
thread unless a memory fence is involved.

You can argue about whether or not it'll actually happen, but I prefer
to work from guarantees when it comes to multi-threading - because
sooner or later, some architecture will come along and destroy all
assumptions apart from the guarantees.

--
Jon Skeet - <(E-Mail Removed)>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
 
Reply With Quote
 
Jon Skeet [C# MVP]
Guest
Posts: n/a
 
      24th Feb 2004
Dennis Owens <(E-Mail Removed)> wrote:
> The interrrupt was just a wild guess to try and stop it from sucking
> up all the processor time. I forgot I left it in there. The only line
> in that method should be the adding of the row in the dataset. As for
> your second thing, is this what is causing the thread to take over.
> Well I will lookup Control.Invoke and see if I can figure it out. I
> still don't see the eight threads, just the form and the test thread?


Sorry, I thought you'd meant there were 8 clicks, not 8 events -
misread. Yup, there'll only be the one extra thread. It will still be
in a tight loop though, which is going to stuff you to some extent
*whatever* you do.

--
Jon Skeet - <(E-Mail Removed)>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
 
Reply With Quote
 
Jon Skeet [C# MVP]
Guest
Posts: n/a
 
      24th Feb 2004
Valery Pryamikov <(E-Mail Removed)> wrote:
> btw (for avoiding being misinterpreted) I didn't say that using bool flag as
> thread event is good design :-). He should use kernel object like event for
> signaling exit.


On the contrary, I'd say using a boolean (but using it properly) is a
perfectly reasonable way of exiting the thread. How would your code
with an event work? It's basically going to end up doing something
*equivalent* to just checking a flag, assuming that the thread wants to
keep doing work until it's told to stop.

Using a boolean is simple (when done right) and allows clean exit
(unlike, say, aborting the thread). Sure, it requires a memory barrier
in order to guarantee that the thread sees the appropriate change in
value, but those are very cheap in the grand scheme of things. What
benefit is there in doing anything else?

--
Jon Skeet - <(E-Mail Removed)>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
datasets, datagrids, and datatables =?Utf-8?B?bWVsYW5pZWFi?= Microsoft C# .NET 2 16th Aug 2005 09:07 PM
problems with multithreading, datasets and datagrids =?Utf-8?B?QWxleCBTbW90cml0c2t5?= Microsoft Dot NET Framework Forms 0 16th May 2005 01:52 PM
DataGrids, Datasets and ListBoxes =?Utf-8?B?SmFtZXMgQmF0bGV5?= Microsoft Dot NET Framework Forms 1 5th Nov 2004 07:37 AM
Rounding Datasets/Datagrids Les Hughes Microsoft VB .NET 2 28th Sep 2004 01:07 AM
Threads datatables and datagrids =?Utf-8?B?a2s=?= Microsoft Dot NET Framework Forms 0 29th Jul 2004 09:42 AM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 07:32 PM.