48

スレッドセーフであるはずのこの小さなメソッドがあります。void ではなく戻り値が必要になるまで、すべてが機能します。BeginInvoke が呼び出されたときに戻り値を取得するにはどうすればよいですか?

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

    }

編集:スレッドを続行する前に GUI からの値が必要なため、この場合、BeginInvoke は必要ではないと思います。そのため、Invoke を使用することも有効です。次の例でそれを使用して値を返す方法の手がかりはありません。

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

    }

しかし、そのコードを使用して値を取得する方法もわかりません;)

4

7 に答える 7

76

関数が戻るのを待って戻り値を取得できるように、 Invoke() する必要があります。別のデリゲート タイプも必要です。これはうまくいくはずです:

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;
  }
}
于 2010-02-06T18:09:39.663 に答える
20

EndInvoke呼び出しから戻り値を取得するために使用できBeginInvokeます。例えば:

    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);
    }
}
于 2010-02-06T18:23:07.970 に答える
4
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;
}
于 2010-02-06T18:19:05.810 に答える
2

メソッドからの戻り値が必要な場合は、非同期バージョンのメソッドを使用しないでください。使用する必要があります.Invoke(...)。これは同期的です。つまり、デリゲートを実行し、完了するまで戻りません。現在の例では、BeginInvoke はリクエストを送信してデリゲートを実行し、すぐに戻ります。したがって、返すものは何もありません。

于 2010-02-06T17:48:08.557 に答える
2

このようなものがあなたが望んでいたものですか?

// 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);
于 2010-02-06T17:48:35.437 に答える
0
delegate string StringInvoker();
    string GetControlText()
    {
        if (control.InvokeRequired)
        {
            string controltext = (string)control.Invoke(new StringInvoker(GetControlText));
            return(controltext);
        }
        else
        {
            return(control.Text);
        }
    }

// シンプルでエレガントですが、別のスレッドがデリゲートを実行するのを待つ必要があります。ただし、結果なしで続行できない場合は...

于 2014-01-21T11:48:13.030 に答える