473,322 Members | 1,188 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,322 software developers and data experts.

Events - thread safe?

I am trying to learn how to create an application that uses worker threads
to prevent the UI from freezing up.
My question is: Is the following code considered "thread safe"?
If not, what am I doing wrong?

Thanks
Dan

--------------------------------------------------------
I have a form with this code:
--------------------------------------------------------
private void button1_Click(object sender, System.EventArgs e)

{

WorkerClass wc = new WorkerClass();

wc.ProcessComplete+= new WorkerClass.ProcessCompleteHandler(WorkerDone);

wc.Process();

Console.WriteLine("Waiting for worker thread");

}

public void WorkerDone(long current)

{

Console.WriteLine("main: Worker thread complete" + current.ToString());

this.textBox1.Text = current.ToString();

}

--------------------------------------------------------

A also have a seperate class with this code:

--------------------------------------------------------

using System;

using System.Threading;

namespace TestWorkerThread

{

/// <summary>

/// Summary description for WorkerClass.

/// </summary>

public class WorkerClass

{

long Result;

public delegate void ProcessCompleteHandler(long current);

public event ProcessCompleteHandler ProcessComplete;

public WorkerClass()

{

//

// TODO: Add constructor logic here

//
}

public void Process()

{
// Create a new thread and call a function on that new thread.

// This method should return without waiting
ThreadStart myThreadDelegate = new ThreadStart(ProcessData);

Thread myThread = new Thread(myThreadDelegate);

myThread.Start();

}

private void ProcessData()

{

Result = 0;
for (int x = 0; x<10; x++)

{

Result = Result + x;

Thread.Sleep(1000);

}
// Fire the event signal. Any subscribers will then know the processing is
done.

OnProcessComplete(Result);

}

protected void OnProcessComplete(long current)

{

ProcessComplete(current);

}

}

}

----------------------------------------------------------------




Mar 15 '06 #1
5 2376
Dan,

Events are fired on the thread that they are called from. Because of
this, your ProcessCompleteHandler which sets the text in the textbox is not
correct.

What you need to do is have your call to set the Text property of the
TextBox on the UI thread. You can do this like this:

// Define the delegate.
delegate void WorkerDoneCallback(long current);

Then, when you set up the callback for the ProcessCompleteHandler, I
would do the following:

wc.ProcessComplete += delegate(long current)
{
// Call the WorkerDone method on the UI thread.
this.Invoke(new WorkerClass.ProcessCompleteHandler(WorkerDone), new
object[1]{current});
}

Basically, you have set up an anonymous delegate which will call your
WorkerDone method through the Invoke method on the Control.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com
"Dan Tallent" <sp**@microsoft.com> wrote in message
news:e%***************@TK2MSFTNGP14.phx.gbl...
I am trying to learn how to create an application that uses worker threads
to prevent the UI from freezing up.
My question is: Is the following code considered "thread safe"?
If not, what am I doing wrong?

Thanks
Dan

--------------------------------------------------------
I have a form with this code:
--------------------------------------------------------
private void button1_Click(object sender, System.EventArgs e)

{

WorkerClass wc = new WorkerClass();

wc.ProcessComplete+= new WorkerClass.ProcessCompleteHandler(WorkerDone);

wc.Process();

Console.WriteLine("Waiting for worker thread");

}

public void WorkerDone(long current)

{

Console.WriteLine("main: Worker thread complete" + current.ToString());

this.textBox1.Text = current.ToString();

}

--------------------------------------------------------

A also have a seperate class with this code:

--------------------------------------------------------

using System;

using System.Threading;

namespace TestWorkerThread

{

/// <summary>

/// Summary description for WorkerClass.

/// </summary>

public class WorkerClass

{

long Result;

public delegate void ProcessCompleteHandler(long current);

public event ProcessCompleteHandler ProcessComplete;

public WorkerClass()

{

//

// TODO: Add constructor logic here

//
}

public void Process()

{
// Create a new thread and call a function on that new thread.

// This method should return without waiting
ThreadStart myThreadDelegate = new ThreadStart(ProcessData);

Thread myThread = new Thread(myThreadDelegate);

myThread.Start();

}

private void ProcessData()

{

Result = 0;
for (int x = 0; x<10; x++)

{

Result = Result + x;

Thread.Sleep(1000);

}
// Fire the event signal. Any subscribers will then know the processing is
done.

OnProcessComplete(Result);

}

protected void OnProcessComplete(long current)

{

ProcessComplete(current);

}

}

}

----------------------------------------------------------------



Mar 15 '06 #2
Dan,

No, it is not thread-safe. Windows controls can only be accessed from
the thread they were created on. Typically, that's the main UI thread.
What you need to do is marshal the execution of a delegate onto that
thread using Control.Invoke.

public void WorkerDone(long current)
{
if (this.InvokeRequired)
{
Delegate method = new ProcessCompleteHandler(this.WorkerDone);
object[] args = new object[] { current };
this.Invoke(method, args);
}
else
{
Console.WriteLine("main: Worker thread complete" +
current.ToString());
this.textBox1.Text = current.ToString();
}
}
Read the following article for more information.

<http://www.yoda.arachsys.com/csharp/threads/winforms.shtml>

Brian

Dan Tallent wrote:
I am trying to learn how to create an application that uses worker threads
to prevent the UI from freezing up.
My question is: Is the following code considered "thread safe"?
If not, what am I doing wrong?

Thanks
Dan

--------------------------------------------------------
I have a form with this code:
--------------------------------------------------------
private void button1_Click(object sender, System.EventArgs e)

{

WorkerClass wc = new WorkerClass();

wc.ProcessComplete+= new WorkerClass.ProcessCompleteHandler(WorkerDone);

wc.Process();

Console.WriteLine("Waiting for worker thread");

}

public void WorkerDone(long current)

{

Console.WriteLine("main: Worker thread complete" + current.ToString());

this.textBox1.Text = current.ToString();

}

--------------------------------------------------------

A also have a seperate class with this code:

--------------------------------------------------------

using System;

using System.Threading;

namespace TestWorkerThread

{

/// <summary>

/// Summary description for WorkerClass.

/// </summary>

public class WorkerClass

{

long Result;

public delegate void ProcessCompleteHandler(long current);

public event ProcessCompleteHandler ProcessComplete;

public WorkerClass()

{

//

// TODO: Add constructor logic here

//
}

public void Process()

{
// Create a new thread and call a function on that new thread.

// This method should return without waiting
ThreadStart myThreadDelegate = new ThreadStart(ProcessData);

Thread myThread = new Thread(myThreadDelegate);

myThread.Start();

}

private void ProcessData()

{

Result = 0;
for (int x = 0; x<10; x++)

{

Result = Result + x;

Thread.Sleep(1000);

}
// Fire the event signal. Any subscribers will then know the processing is
done.

OnProcessComplete(Result);

}

protected void OnProcessComplete(long current)

{

ProcessComplete(current);

}

}

}

----------------------------------------------------------------


Mar 15 '06 #3
I could see how this could work, but what if I want the function in the
worker thread to be independent of a specific form? I thought using
subscribing to events in this manner would allow this. I will take a look
at the link you supplied. Thanks

Dan

"Brian Gideon" <br*********@yahoo.com> wrote in message
news:11**********************@e56g2000cwe.googlegr oups.com...
Dan,

No, it is not thread-safe. Windows controls can only be accessed from
the thread they were created on. Typically, that's the main UI thread.
What you need to do is marshal the execution of a delegate onto that
thread using Control.Invoke.

public void WorkerDone(long current)
{
if (this.InvokeRequired)
{
Delegate method = new ProcessCompleteHandler(this.WorkerDone);
object[] args = new object[] { current };
this.Invoke(method, args);
}
else
{
Console.WriteLine("main: Worker thread complete" +
current.ToString());
this.textBox1.Text = current.ToString();
}
}
Read the following article for more information.

<http://www.yoda.arachsys.com/csharp/threads/winforms.shtml>

Brian

Dan Tallent wrote:
I am trying to learn how to create an application that uses worker
threads
to prevent the UI from freezing up.
My question is: Is the following code considered "thread safe"?
If not, what am I doing wrong?

Thanks
Dan

--------------------------------------------------------
I have a form with this code:
--------------------------------------------------------
private void button1_Click(object sender, System.EventArgs e)

{

WorkerClass wc = new WorkerClass();

wc.ProcessComplete+= new WorkerClass.ProcessCompleteHandler(WorkerDone);

wc.Process();

Console.WriteLine("Waiting for worker thread");

}

public void WorkerDone(long current)

{

Console.WriteLine("main: Worker thread complete" + current.ToString());

this.textBox1.Text = current.ToString();

}

--------------------------------------------------------

A also have a seperate class with this code:

--------------------------------------------------------

using System;

using System.Threading;

namespace TestWorkerThread

{

/// <summary>

/// Summary description for WorkerClass.

/// </summary>

public class WorkerClass

{

long Result;

public delegate void ProcessCompleteHandler(long current);

public event ProcessCompleteHandler ProcessComplete;

public WorkerClass()

{

//

// TODO: Add constructor logic here

//
}

public void Process()

{
// Create a new thread and call a function on that new thread.

// This method should return without waiting
ThreadStart myThreadDelegate = new ThreadStart(ProcessData);

Thread myThread = new Thread(myThreadDelegate);

myThread.Start();

}

private void ProcessData()

{

Result = 0;
for (int x = 0; x<10; x++)

{

Result = Result + x;

Thread.Sleep(1000);

}
// Fire the event signal. Any subscribers will then know the processing
is
done.

OnProcessComplete(Result);

}

protected void OnProcessComplete(long current)

{

ProcessComplete(current);

}

}

}

----------------------------------------------------------------

Mar 15 '06 #4
Ok, I think I get it.

Because the calling function is on a different thread, I need to use the
Invoke method for the WorkerDone method.
And writting the WorkerDone method in this way prevents the WorkerClass from
"needing to know" anything about the form.
The InvokeRequired property is an "allowed" exception to the rule, which
allows me to call it either directly or marshalling it if required.

If I am wrong with this description, please let me know.

I really appreciate your help.

Thanks
Dan
"Dan Tallent" <sp**@microsoft.com> wrote in message
news:OQ**************@TK2MSFTNGP10.phx.gbl...
I could see how this could work, but what if I want the function in the
worker thread to be independent of a specific form? I thought using
subscribing to events in this manner would allow this. I will take a
look at the link you supplied. Thanks

Dan

"Brian Gideon" <br*********@yahoo.com> wrote in message
news:11**********************@e56g2000cwe.googlegr oups.com...
Dan,

No, it is not thread-safe. Windows controls can only be accessed from
the thread they were created on. Typically, that's the main UI thread.
What you need to do is marshal the execution of a delegate onto that
thread using Control.Invoke.

public void WorkerDone(long current)
{
if (this.InvokeRequired)
{
Delegate method = new ProcessCompleteHandler(this.WorkerDone);
object[] args = new object[] { current };
this.Invoke(method, args);
}
else
{
Console.WriteLine("main: Worker thread complete" +
current.ToString());
this.textBox1.Text = current.ToString();
}
}
Read the following article for more information.

<http://www.yoda.arachsys.com/csharp/threads/winforms.shtml>

Brian

Dan Tallent wrote:
I am trying to learn how to create an application that uses worker
threads
to prevent the UI from freezing up.
My question is: Is the following code considered "thread safe"?
If not, what am I doing wrong?

Thanks
Dan

--------------------------------------------------------
I have a form with this code:
--------------------------------------------------------
private void button1_Click(object sender, System.EventArgs e)

{

WorkerClass wc = new WorkerClass();

wc.ProcessComplete+= new WorkerClass.ProcessCompleteHandler(WorkerDone);

wc.Process();

Console.WriteLine("Waiting for worker thread");

}

public void WorkerDone(long current)

{

Console.WriteLine("main: Worker thread complete" + current.ToString());

this.textBox1.Text = current.ToString();

}

--------------------------------------------------------

A also have a seperate class with this code:

--------------------------------------------------------

using System;

using System.Threading;

namespace TestWorkerThread

{

/// <summary>

/// Summary description for WorkerClass.

/// </summary>

public class WorkerClass

{

long Result;

public delegate void ProcessCompleteHandler(long current);

public event ProcessCompleteHandler ProcessComplete;

public WorkerClass()

{

//

// TODO: Add constructor logic here

//
}

public void Process()

{
// Create a new thread and call a function on that new thread.

// This method should return without waiting
ThreadStart myThreadDelegate = new ThreadStart(ProcessData);

Thread myThread = new Thread(myThreadDelegate);

myThread.Start();

}

private void ProcessData()

{

Result = 0;
for (int x = 0; x<10; x++)

{

Result = Result + x;

Thread.Sleep(1000);

}
// Fire the event signal. Any subscribers will then know the processing
is
done.

OnProcessComplete(Result);

}

protected void OnProcessComplete(long current)

{

ProcessComplete(current);

}

}

}

----------------------------------------------------------------


Mar 15 '06 #5
Dan Tallent wrote:
Ok, I think I get it.

Because the calling function is on a different thread, I need to use the
Invoke method for the WorkerDone method.
And writting the WorkerDone method in this way prevents the WorkerClass from
"needing to know" anything about the form.
Yeah, that's right. The WorkerClass doesn't know anything about who is
subscribed to its events. But, the form knows how the WorkerClass
behaves. Specifically, it knows that the WorkerClass' events are not
guarenteed to be executed on the UI thread so the form needs to ensure
that.

There is an alternate design pattern that I've used before. Take a
look at the System.Timers.Timer class. You'll notice that it has a
SynchronizingObject property that accepts an ISynchronizeInvoke object.
Forms and Controls implement ISynchronizeInvoke. Actually, that's the
interface that contains the InvokeRequired, Invoke, etc. methods. When
that property is set to a form or control it will automatically marshal
events and callbacks onto the thread hosting that object. You could do
something similar with your WorkerClass.
The InvokeRequired property is an "allowed" exception to the rule, which
allows me to call it either directly or marshalling it if required.

Yes, InvokeRequired, Invoke, and BeginInvoke are all thread-safe. They
are among the few exceptions.
If I am wrong with this description, please let me know.

I really appreciate your help.

Thanks
Dan


Mar 15 '06 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Steven Brown | last post by:
I'm trying to figure out how to safely use .NET events/delegates in a thread-safe class. There are a couple problems. One is that the standard "if(EventName != null) EventName(...);" call can...
3
by: mikeb | last post by:
I have a class (settings, etc.) which is derived from CollectionBase and contains a number of fields and a few events. When I create an instance of this class in my app, and serialize it, it works....
3
by: Jacob | last post by:
I'm working on a class that needs to be called from a windows form, do it's work, and then, show progress back to the main form. I'm well aware that worker threads need to call Invoke for updates...
2
by: Zürcher See | last post by:
The event is thread safe? If a class call a delegate for an event, is the class thread to execute the code or is the thread that has itself registered that execute the code? In few words if a form...
1
by: Natalia DeBow | last post by:
Hi, I am working on a Windows-based client-server application. I am involved in the development of the remote client modules. I am using asynchronous delegates to obtain information from...
4
by: LP | last post by:
Hello! I am still transitioning from VB.NET to C#. I undertand the basic concepts of Delegates, more so of Events and somewhat understand AsyncCallback methods. But I need some clarification on...
1
by: Tom | last post by:
First of all, is it 'legal' (i.e. thread-safe) to pass events back from a worker thread to the main thread? I.E. Can one put PUBLIC EVENT XYZ in their worker thread and then raise that event for...
9
by: CuriousGeorge | last post by:
Can someone explain why this code DOES NOT raise a null reference exception? //////////////////////////// Program.cs ///////////////////////////////////////////// using System; using...
15
by: damiensawyer | last post by:
Hi, I am creating a class (from a base class) that needs to trigger events (code at bottom). I am instatiating the classes and wiring up the events as follows. clsDetermineConnection oDC =...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.