Worker Thread and UI thread changes

qex

Regular
Joined
Apr 2, 2003
Messages
78
When using threads I've read in plenty of places that you are not to modify UI Controls from inside worker threads and they usualy go on to say that you should use invoke to make any changes.

If I create a class and the worker thread started is given a method within that class that contains events that can be called is that the same thing or at least another way of accomplishing the same thing.

For example this psuedo code example...
Code:
class myClass
{
   public myClass()
   {
   }

   //
   public void WorkerMethod()
   {
      //Do Something
      EventArgs e = new EventArgs();
      OnSomeException(e);
   }
   public delegate void SomeErrorEventHandler(EventArgs e);
   public event SomeErrorEventHandler SomeException;
   protected virtual void OnSomeException(EventArgs e)
   {
     if(SomeException != null)
     {
	SomeException(e);
     }
   }
}
myClass myC = new myClass()  //class declaration
void main()
{
  myC.SomeException += SomeErrorEventHandler(EventArgs e);
  Thread myThread = new Thread(newThreadStart(myC.WorkerMethod()));
  myThread.Start();
}

//declare a function that will handle the SomeErrorEventHander
//and modify the user interface

I think this is ok since the whole point of using invoke is that the modification of the UI happens on the UI thread and thats what this accomplishes. Is this correct?
 
With Invoke, you mean invoking the event?

If that is so, than no, this doesn't count as getting the handling on the UI thread. Actually, without using some special construction, events are handled synchronuous on the thread that invokes them.

You can test this by using the InvokeRequired property in the method that is called when the event is invoked.

However, it doesnt require much code in the method that is invoked to handle the exception, something like this would sufficient to correctly handle the event
Code:
//The error handler that is invoked by the worker thread
public void MyErrorHandler(EventArgs e)
{
  //Check if this is on the UI thread or not
  if (this.InvokeRequired)
  {
    //not on UI thread -> invoke it so it is on the UI thread
    ProgressTitleUpdate delUpdate = new SomeErrorEventHandler(MyErrorHandler);
    object[] args = {e};
    //BeginInvoke -> async. You can also use Invoke to make it synchronuous. 
    // In either case it is handled on the UI thread.
    BeginInvoke(del, args);
  }
  else
  {
    //Do whatever needs done with the exception, this code is running on the UI thread
  }
}

The difference is that the (Begin)Invoke / InvokeRequired methods are used of the ISynchronizeInvoke interface. This is an interface used at the Control baseclass of UI elements. This interface allows you to synchronize to the UI thread. Only through these methods can you be sure if the events fired from your worker thread are handled on the UI thread if necessary.
 
So what your saying is the example I gave is bad and I should not be doing that?
 
That depends on the design of the rest of your software.

All I'm saying is that it wont fix the worker thread vs UI thread problem.
 
No, problem it's actually not a bad thing it may explain some flakey behavior that I have seen in certain circumstances... Thats what I'm hoping for at least... Thanks!
 
I have read in several places where they say if you use BeginInvoke you should use EndInvoke as it could leak memory if you do not.
 
Normally yes but there are 2 ways to not directly call the endinvoke as far as I know.

Use a callback in the begininvoke. When the invoked method is finished, the callback method is called so you can call endinvoke from that callback.

The second way is by using the System.Runtime.Remoting.Messaging.OneWayAttribute attribute on the method invoked. This means the invoked methods can't throw exceptions or return parameters. It also means that the caller has no guarantee when the invoked method is finished. But it should also mean that there is no administration kept by the .net framework when the method is finished.

Off course, both methods are a bit heavy for just updating the some simple text in the UI ;). Just Invoke probably is a lot simpler to implement and works just as well ;).
 
Back
Top