如何在C#中调用BeginInvoke/Invoke时获取返回值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2214002/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get return value when BeginInvoke/Invoke is called in C#
提问by MadBoy
I've this little method which is supposed to be thread safe. Everything works till i want it to have return value instead of void. How do i get the return value when BeginInvoke is called?
我有这个应该是线程安全的小方法。一切正常,直到我希望它具有返回值而不是 void。调用 BeginInvoke 时如何获取返回值?
public static string readControlText(Control varControl) {
if (varControl.InvokeRequired) {
varControl.BeginInvoke(new MethodInvoker(() => readControlText(varControl)));
} else {
string varText = varControl.Text;
return varText;
}
}
Edit: I guess having BeginInvoke is not nessecary in this case as i need value from GUI before the thread can continue. So using Invoke is good as well. Just no clue how to use it in following example to return value.
编辑:我想在这种情况下使用 BeginInvoke 不是必要的,因为在线程继续之前我需要来自 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;
}
}
But not sure how to get value using that code either ;)
但不确定如何使用该代码获取价值;)
采纳答案by Hans Passant
You have to Invoke() so you can wait for the function to return and obtain its return value. You'll also need another delegate type. This ought to work:
您必须调用 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;
}
}
回答by THX-1138
If you want a return value from you method, you shouldn't be using async version of the method, you should use .Invoke(...)
. Which is synchronous, that is it will execute your delegate, and won't return until it's complete. In your example as it is now, BeginInvoke will send the request to execute your delegate, and return right away. So there is nothing to return.
如果您想要方法的返回值,则不应使用该方法的异步版本,而应使用.Invoke(...)
. 这是同步的,即它将执行您的委托,并且在完成之前不会返回。在您现在的示例中,BeginInvoke 将发送请求以执行您的委托,并立即返回。所以没有什么可以返回的。
回答by Randy Minder
Is something like this what you wanted?
这是你想要的吗?
// 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);
回答by Sergey Teplyakov
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;
}
回答by Justin Ethier
EndInvoke
may be used to get a return value from a BeginInvoke
call. For example:
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);
}
}
回答by Pablo
delegate string StringInvoker();
string GetControlText()
{
if (control.InvokeRequired)
{
string controltext = (string)control.Invoke(new StringInvoker(GetControlText));
return(controltext);
}
else
{
return(control.Text);
}
}
//simple & elegant but it is needed to wait for another thread to execute delegate; however if you cannot proceed without the results...
//简单而优雅,但需要等待另一个线程执行委托;但是,如果没有结果就无法继续...