wake-up-neo.com

Wie erhalte ich einen Rückgabewert, wenn BeginInvoke/Invoke in C # aufgerufen wird

Ich habe diese kleine Methode, die fadensicher sein soll. Alles funktioniert, bis ich will, dass es einen Rückgabewert hat, anstatt leer zu sein. Wie erhalte ich den Rückgabewert, wenn BeginInvoke aufgerufen wird? 

public static string readControlText(Control varControl) {
        if (varControl.InvokeRequired) {
            varControl.BeginInvoke(new MethodInvoker(() => readControlText(varControl)));
        } else {
            string varText = varControl.Text;
             return varText;
        }

    }

Edit: Ich denke, BeginInvoke zu haben ist in diesem Fall nicht notwendig, da ich einen Wert von GUI benötige, bevor der Thread fortgesetzt werden kann. Die Verwendung von Invoke ist also auch gut. Keine Ahnung, wie Sie ihn im folgenden Beispiel verwenden können, um den Wert zurückzugeben. 

private delegate string ControlTextRead(Control varControl);
    public static string readControlText(Control varControl) {
        if (varControl.InvokeRequired) {
            varControl.Invoke(new ControlTextRead(readControlText), new object[] {varControl});
        } else {
            string varText = varControl.Text;
             return varText;
        }

    }

Aber nicht sicher, wie man mit diesem Code Wert bekommt;)

36
MadBoy

Sie müssen Invoke () aufrufen, damit Sie warten können, bis die Funktion ihren Rückgabewert zurückgibt. Sie benötigen auch einen anderen Delegatentyp. Das sollte funktionieren:

public static string readControlText(Control varControl) {
  if (varControl.InvokeRequired) {
    return (string)varControl.Invoke(
      new Func<String>(() => readControlText(varControl))
    );
  }
  else {
    string varText = varControl.Text;
    return varText;
  }
}
56
Hans Passant

EndInvoke kann verwendet werden, um einen Rückgabewert von einem BeginInvoke-Aufruf abzurufen. Zum Beispiel:

    public static void Main() 
    {
        // The asynchronous method puts the thread id here.
        int threadId;

        // Create an instance of the test class.
        AsyncDemo ad = new AsyncDemo();

        // Create the delegate.
        AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);

        // Initiate the asychronous call.
        IAsyncResult result = caller.BeginInvoke(3000, 
            out threadId, null, null);

        Thread.Sleep(0);
        Console.WriteLine("Main thread {0} does some work.",
            Thread.CurrentThread.ManagedThreadId);

        // Call EndInvoke to wait for the asynchronous call to complete,
        // and to retrieve the results.
        string returnValue = caller.EndInvoke(out threadId, result);

        Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
            threadId, returnValue);
    }
}
17
Justin Ethier
public static string readControlText(Control varControl)
{
    if (varControl.InvokeRequired)
    {
        string res = "";
        var action = new Action<Control>(c => res = c.Text);
        varControl.Invoke(action, varControl);
        return res;
    }
    string varText = varControl.Text;
    return varText;
}
4

Wenn Sie einen Rückgabewert von Ihrer Methode wünschen, sollten Sie keine asynchrone Version der Methode verwenden. Sie sollten .Invoke(...) verwenden. Welches ist synchron, das heißt, es wird Ihren Stellvertreter ausführen und nicht zurückkehren, bis es vollständig ist. In Ihrem aktuellen Beispiel sendet BeginInvoke die Anforderung zur Ausführung Ihres Delegaten und kehrt sofort zurück. Es gibt also nichts zurückzukehren.

2
THX-1138

Wolltest du so etwas?

// begin execution asynchronously
IAsyncResult result = myObject.BeginInvoke("data.dat", null, null);

// wait for it to complete
while (result.IsCompleted == false) {
   // do some work
   Thread.Sleep(10);
   }

// get the return value
int returnValue = myObject.EndInvoke(result);
1
Randy Minder
delegate string StringInvoker();
    string GetControlText()
    {
        if (control.InvokeRequired)
        {
            string controltext = (string)control.Invoke(new StringInvoker(GetControlText));
            return(controltext);
        }
        else
        {
            return(control.Text);
        }
    }

// einfach und elegant, aber es muss ein anderer Thread gewartet werden, um delegate auszuführen Wenn Sie jedoch ohne die Ergebnisse nicht fortfahren können ...

0
Pablo