Reputation: 850
I have a class with a Socket, listens to clients to receive data. When receive new data I want to call an event (if implemented) but as you know every connection has its own thread so the event will run at that thread and you know the rest. you can not work with form controls. How do I call the event (or invoke it). I'm really new to thread and network programing so I appreciate any example.
public class HVremotechooser
{
public delegate void NewOrder(Order order);
public event NewOrder nOrder;
//... (code elided)
public void ReceiveCallback(IAsyncResult AsyncCall) // new connection of client
{
//... (code elided)
if (nOrder != null)
nOrder(Order); // calling the event "nOrder"
//... (code elided)
}
}
thank you.
Upvotes: 1
Views: 214
Reputation: 7452
UI Threading is a UI concern. In my opinion you shouldn't worry about invoking to the ui thread in this code. Rather the consumer of the event should do the Invoke
or whatever other threading stuff they happen to need to do. That way if the UI person needs to change their strategy (e.g. by using a timer) your non-UI related code wont need to change.
Upvotes: 0
Reputation: 48949
You can use the typical marshling operations like Invoke
or BeginInvoke
to inject the execution of a delegate onto the UI thread. Just pass an instance of ISynchronizeInvoke
or SynchronizationContext
to your class to facilitate the marshaling.
However, I would not do that in your case. Since, presumably anyway, these callbacks are occuring because of socket events it is possible likely they are coming in hard and heavy. You definitely do not want to slam your UI thread with all of that activity. Instead, package up all of the pertinent data and put into a collection that the UI thread can then poll for using a System.Windows.Forms.Timer
on a more reasonable interval.
I rip on these marshling operations all of the time. They are way overrated and overused. Remember, there are two general methods of sharing data and signaling between UI and worker threads.
Invoke
or BeginInvoke
in the worker threadSystem.Windows.Forms.Timer
in the UI threadThe pull method can be, and often is, more elegant.
Upvotes: 0
Reputation: 22945
If you want to update your form from a non-UI thread, you have to invoke the action. What I normally do is the following:
private void LongRunningBackgroundThread() {
// lots of work
...
// Update my form
InvokeIfRequired(() => {
...update form...
}
}
private static void InvokeIfRequired(Action a) {
if (control.InvokeRequired) {
control.Invoke(a);
} else {
a();
}
}
Upvotes: 1
Reputation: 271
I ran into a similar problem with a Silverlight application that I was working on last week, and used the Dispatcher.BeginInvoke method. With Windows forms, it looks like it might be easier to use Control.BeginInvoke instead (although I believe that either should work): http://msdn.microsoft.com/en-us/library/system.windows.forms.control.begininvoke.aspx
Upvotes: 0