Frage

Leider Application.Invoke() ist asynchron:

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

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

    return result;
}

Das bedeutet, dass in diesem Beispiel ThreadFunction() geht unmittelbar nach Application.Invoke() Aufruf, was zu einem wahrscheinlich undefinierten Zustand des result String. -. ThreadFunction() wird schneller sein und wird mit dem alten Wert zurück (das heißt null)

Normalerweise


Dies ist eine Abhilfe ManualResetEvent mit Application.Invoke() synchron zu machen:

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;
}

Auf diese Weise wartet ThreadFunction() bis Application.Invoke() zurückkehrt, wie es mit täte WinForms Control.Invoke () .

EDIT: Besserer Beispiel-Code

EDIT2: Fehlende using


Nun meine Frage: Gibt es eine bessere Lösung

War es hilfreich?

Lösung

Nun ja, es gibt keinen Grund zu warten, bis die Delegierten den richtigen Rückgabewert zu erhalten auszuführen. Fix:

int result = i + 1;

Und es ist in Ordnung, die OutputStringToUserInterface () ausführt asynchron zu lassen, Sie unter der Annahme, rufen Sie nicht ThreadFunction () so oft, dass es den UI-Thread mit Anfragen überschwemmt.

Wenn Sie Ihr echter Code tatsächlich abhängig von einem Rückgabewert einer Funktion, die dann auf dem UI-Thread ausgeführt werden muß, nein, können Sie es nicht schneller. Klar, das ist etwas, das Sie wirklich zu vermeiden.

Andere Tipps

Sie können Ihren aktuellen Code in einen generischen Wrapper kapseln:

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();});
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top