在C#中调用BeginInvoke / Invoke时如何获取返回值

时间:2010-02-06 17:44:49

标签: c# .net multithreading invoke begininvoke

我有一个本应该是线程安全的小方法。一切正常,直到我希望它具有回报价值而不是虚空。如何在调用BeginInvoke时获得返回值?

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

    }

编辑:我想在这种情况下让BeginInvoke不是nessecary,因为我需要来自GUI的值才能继续线程。所以使用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;
        }

    }

但不确定如何使用该代码获取价值;)

6 个答案:

答案 0 :(得分:57)

您必须调用(),以便等待函数返回并获取其返回值。您还需要另一个委托类型。这应该有效:

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

答案 1 :(得分:17)

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

答案 2 :(得分: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;
}

答案 3 :(得分:2)

如果你想从你的方法返回值,你不应该使用该方法的异步版本,你应该使用.Invoke(...)。哪个是同步的,即它将执行您的委托,并且在完成之前不会返回。在您的示例中,BeginInvoke将发送执行您的委托的请求,并立即返回。所以没有什么可以回归的。

答案 4 :(得分:1)

这是你想要的吗?

// 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);

答案 5 :(得分:0)

delegate string StringInvoker();
    string GetControlText()
    {
        if (control.InvokeRequired)
        {
            string controltext = (string)control.Invoke(new StringInvoker(GetControlText));
            return(controltext);
        }
        else
        {
            return(control.Text);
        }
    }

//简单&amp;优雅,但需要等待另一个线程执行委托;但如果没有结果你就无法继续......