Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use ISynchronizeInvoke without a reference to the Form

I need to "send" a piece of code from another thread (Excel Interop) to the UI thread to execute. Normally you'd use Invoke on the Form, which implements the ISynchronizeInvoke interface:

public class MyForm : Form
{
    ...
    private void Button_Click(object sender, EventArgs e)
    {
        SomeExcelWorkbook.OnBeforeClose += delegate(ref bool Cancel)
        {
            this.Invoke(someCode);
        };
    }
}

Unfortunately there is a layer of abstraction between the form code and the code that defines the event handler, and I don't have a reference to the form at that point:

public void CodeExecutedByUIThread()
{
    ISynchronizeInvoke sync;
    SomeExcelWorkbook.OnBeforeClose += delegate(ref bool Cancel)
    {
        sync.Invoke(someCode);
    };
}

When entering CodeExecutedByUIThread, we are still in the UI thread, so in theory everything needed should be there. Unfortunately the Form is the only class implementing that interface, is it?

How can I get an ISynchronizeInvoke from within the UI thread? Apparently Thread.CurrentThread doesn't provide it...

Or is there a way to get a SynchronizationContext? How would I retrieve and use that?

Update: Oh, I see, getting the SynchronizationContext object looks as simple as SynchronizationContext.Current, which doesn't need any reference to a form. So I'll google little bit more about how to use that.

like image 487
chiccodoro Avatar asked Oct 05 '10 09:10

chiccodoro


1 Answers

In general, I think that neither is possible.

This might seem like an obvious answer, but what we used in this case was to store both the SynchronizationContext and the reference to the Form (as an ISynchronizeInvoke) in a static class at application startup.

MainForm main = new MainForm();
EnvironmentService.UI = main;
EnvironmentService.UIContext = SynchronizationContext.Current;
Application.Run(main);
like image 139
matiash Avatar answered Oct 07 '22 11:10

matiash