Reputation: 121
I have a class that exposes a public Event. There are various controls on the GUI that can register their event handlers with this Event to make changes to the controls such as text or back color etc. However, the class that exposes the Event does not keep any references of the UI controls those may have added their event handlers.
During the execution, a separate foreground thread executes a method that will invoke (fire) the public Event. This calls the event handlers that have registered with the event.
The problem is that the event handlers are called on the foreground thread and not on UI thread. How do I marshall the call to the UI thread without the reference of the UI controls?
Upvotes: 2
Views: 1666
Reputation: 2235
If your concern is to marshall the event call to your (unique) UI thread the ISynchronizeInvoke
is all you need.
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form mainForm = new MyForm();
// Initialize the service.
MyService service = new MyService(mainForm);
Application.Run(mainForm);
}
public class MyService
{
public event EventHandler MyEvent;
private readonly ISynchronizeInvoke synchronizeInvoke;
public MyService(ISynchronizeInvoke synchronizeInvoke)
{
this.synchronizeInvoke = synchronizeInvoke;
}
private void OnMyEvent()
{
if (MyEvent != null)
{
if (synchronizeInvoke.InvokeRequired)
{
synchronizeInvoke.BeginInvoke(new Action(() => MyEvent(this, EventArgs.Empty)), null);
}
else
{
MyEvent(this, EventArgs.Empty);
}
}
}
}
Upvotes: 3
Reputation: 4554
You can get an open form using Application.OpenForms().
Form form = System.Windows.Forms.Application.OpenForms().FirstOrDefault();
if (form != null)
form.Invoke((MethodInvoker)delegate(){ event(); });
Upvotes: 2
Reputation: 1502156
You need to decide what's going to do the marshalling: the event raiser, or the event handlers. If you don't want the event raiser to know anything about threading - e.g. via ISynchronizeInvoke
or SynchronizationContext
- then make the event handlers do the marshalling instead.
Basically either the event raiser should guarantee that it will raise all events in a particular context (which could be given to it on construction via SynchronizationContext
) or it should make it clear that it's not doing so, and put the onus on the handlers. The latter is the more flexible approach - it means that if you have several handlers with different needs, each can do the appropriate thing for its own needs.
Upvotes: 3