Question

Unfortunately, Application.Invoke() is asynchronous:

private string ThreadFunction(int i)
{
    string result = null;

    Gtk.Application.Invoke(delegate
    {
        OutputStringToUserInterface("i = " + i.ToString());
        result = GetStringFromUserInterface();
    });

    return result;
}

This means that in this example ThreadFunction() proceeds immediately after calling Application.Invoke(), resulting in an probably undefined state of the result string. -- Typically ThreadFunction() will be faster and will return with the old value (i.e. null).


This is a workaround using ManualResetEvent to make Application.Invoke() synchronous:

private string ThreadFunction(int i)
{
    string result = null;

    using (var ev = new ManualResetEvent(false))
    {
        Gtk.Application.Invoke(delegate
        {
            OutputStringToUserInterface("i = " + i.ToString());
            result = GetStringFromUserInterface();

            ev.Set();
        });

        ev.WaitOne();
    }

    return result;
}

This way, ThreadFunction() waits until Application.Invoke() returns, like it would do using WinForms Control.Invoke().

EDIT: Better example code

EDIT2: Add missing using


Now my question: Is there a better solution?

Was it helpful?

Solution

Well, yes, there's no reason to wait for the delegate to execute to get the proper return value. Fix:

int result = i + 1;

And it's okay to let the OutputStringToUserInterface() execute asynchronously, assuming you don't call ThreadFunction() so often that it floods the UI thread with requests.

If your real code actually depends on a return value from a function that must run on the UI thread then, no, you can't make it faster. Clearly, that's something you really want to avoid.

OTHER TIPS

You can encapsulate your current code into a generic wrapper:

public static void GuiInvoke(Action action)
{
    var waitHandle = new ManualResetEventSlim();
    Gtk.Application.Invoke( (s,a) => 
                            {
                                action();
                                waitHandle.Set();
                            });
    waitHandle.Wait();
}

public static void BeginGuiInvoke(Action action)
{
    Gtk.Application.Invoke( (s,a) => {action();});
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top