views:

622

answers:

6

I currently have a thread that listens for data from the network and then runs rules on it. I then want to pass the data to the GUI. I am worried about having a deadlock in the GUI. I cant figure out were to put the mutexes on the GUI side. I am also using c# and dotnet 3.5.

What I have come up with is 1) Using a timer to create an event and dump the thread. Worried about performance. 2) Use an intermediary event to copy the data to GUI. 3) Dig in and figure out thread safe way of using GUI.

What do you think is best way to proceed?

Edit: Here is the solution I am using. I pass in the changed element and then protect the big object with a mutex. I use helper function to switch threads using InvokeRequired then BeginInvoke with a delegate. Pulled from reading the answers and then following links until reaching Threading in Windows Forms by Jon Skeet.

  delegate void UInt32ParameterDelegate(UInt32 n);

  public void UpdateLocation(UInt32 n)
  {
     if (InvokeRequired)
     {
        // We're not in the UI thread, so we need to call BeginInvoke
        BeginInvoke(new UInt32ParameterDelegate(UpdateLocation), new object[] { n });
        return;
     }
     // Must be on the UI thread if we've got this far

     this.engine.location.UpdateBusy.WaitOne();
     // do the work in here

     this.engine.location.UpdateBusy.ReleaseMutex();

  }
A: 

Isn't easier to just throw a delegate who raise an event that inform the form to refresh itself?

gbianchi
+2  A: 

Never read from the network on the GUI thread. It's only a matter of time before your application runs during a network outage and your GUI hangs as a result. This will really frustrate your users.

In your situation I think the best approach is to have a background thread complete the read operation. Then take the resulting data and move it back to the GUI thread via a SynchronizationContext Post or Send method.

JaredPar
+3  A: 

I hope I understand your problem correctly.

After the background thread reads the data and does whatever it wants, it should use Invoke to call a method on the GUI thread. That method would update anything that should be updated in the GUI.

configurator
+1  A: 

you should just pass an event from your network thread to your UI thread.

then cross threads using begininvoke so you don't get a cross thread exception.

http://stackoverflow.com/questions/229254/need-help-getting-info-across-a-ui-thread-and-another-thread-in-c/229292#229292

Hath
+1  A: 

You could use a backgroundworker that will process the datareading in a background thread and when it's done you can end the backgroundworker triggering it's RunWorkerCompletedEventHandler. In the RunWorkerCompletedEventHandler you can update your GUI thread with the result.

Mez
+2  A: 

Synchronization is very easy in Windows Forms. You can call Control.Invoke() in the background thread. The thread will stall until the delegate has finished running on the UI thread. No sync required at all.

If stalling the thread is a problem, use Control.BeginInvoke(). You'll have to protect the object(s) you pass to the delegate with a lock if the thread might alter them while it continues running. That's rarely the case in a producer-consumer scenario, the thread can simply create new objects.

Do make sure that you don't Invoke() too often. Do it more frequently than about 1000 times per second and the UI thread will stop pumping Windows messages, being bogged down by handling the invoke requests. Since it is human eyes you're trying to please, invoking more than about 25 times per second is just wasted effort. Pool intermediate results in a collection object.

Hans Passant