Trying to understand use async await to done some work and something just doesn't work. have a code:
试图理解使用异步等待完成一些工作而某些东西不起作用。有一个代码:
private async Task<string> getStringAsync()
{
var tsk = await Task.Run<string>(() =>
{
Task.Delay(2000);
return "helloWorld";
});
return tsk;
}
private void button2_Click(object sender, EventArgs e)
{
tbLog.Text += getStringAsync().Result;
}
the problem is that getStringAsync().Result
never returns anything. though according to documentation it should:
问题是getStringAsync()。结果永远不会返回任何内容。虽然根据文件它应该:
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/await
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/await
What I am doing wrong?
我做错了什么?
1 个解决方案
#1
3
You're using Result
, which blocks until the task completes. You're using that from the UI thread. So the UI thread will be blocked until the task completes.
您正在使用Result,它会阻塞,直到任务完成。您正在使用UI线程中的那个。因此UI线程将被阻止,直到任务完成。
Now, that task comes from getStringAsync
, which uses await (something)
. As the "something" in this case won't have completed by the time it's awaited (because it's a two second delay), you're saying "Call me back when that's finished." But because you're just using await
(with no ConfigureAwait(false)
), you're saying "call me back on the UI thread".
现在,该任务来自getStringAsync,它使用await(某事物)。由于这种情况下的“某事”在等待的时候还没有完成(因为这是两秒钟的延迟),你说的是“当它完成时给我回电话”。但是因为你只是在使用await(没有ConfigureAwait(false)),所以你会说“在UI线程上给我回电话”。
So you end up with a deadlock: the UI thread is waiting for the getStringAsync()
task to complete, but that task can't complete until its callback has been executed on the UI thread.
所以最终会出现死锁:UI线程正在等待getStringAsync()任务完成,但是在UI线程上执行了回调之前,该任务无法完成。
Note that your tsk
variable isn't a task as one might expect from the name - it's a string, because you're awaiting the Task<string>
.
请注意,您的tsk变量不是人们可能期望的任务 - 它是一个字符串,因为您正在等待Task
The simplest solution is not to use Result
at all. Instead, make your event handler async
and use await
from that too:
最简单的解决方案是根本不使用Result。相反,让你的事件处理程序异步并使用await:
private async Task<string> GetStringAsync()
{
var text = await Task.Run(() =>
{
Task.Delay(2000);
return "helloWorld";
});
return text;
}
private async void HandleButton2Click(object sender, EventArgs e)
{
tbLog.Text += await GetStringAsync();
}
#1
3
You're using Result
, which blocks until the task completes. You're using that from the UI thread. So the UI thread will be blocked until the task completes.
您正在使用Result,它会阻塞,直到任务完成。您正在使用UI线程中的那个。因此UI线程将被阻止,直到任务完成。
Now, that task comes from getStringAsync
, which uses await (something)
. As the "something" in this case won't have completed by the time it's awaited (because it's a two second delay), you're saying "Call me back when that's finished." But because you're just using await
(with no ConfigureAwait(false)
), you're saying "call me back on the UI thread".
现在,该任务来自getStringAsync,它使用await(某事物)。由于这种情况下的“某事”在等待的时候还没有完成(因为这是两秒钟的延迟),你说的是“当它完成时给我回电话”。但是因为你只是在使用await(没有ConfigureAwait(false)),所以你会说“在UI线程上给我回电话”。
So you end up with a deadlock: the UI thread is waiting for the getStringAsync()
task to complete, but that task can't complete until its callback has been executed on the UI thread.
所以最终会出现死锁:UI线程正在等待getStringAsync()任务完成,但是在UI线程上执行了回调之前,该任务无法完成。
Note that your tsk
variable isn't a task as one might expect from the name - it's a string, because you're awaiting the Task<string>
.
请注意,您的tsk变量不是人们可能期望的任务 - 它是一个字符串,因为您正在等待Task
The simplest solution is not to use Result
at all. Instead, make your event handler async
and use await
from that too:
最简单的解决方案是根本不使用Result。相反,让你的事件处理程序异步并使用await:
private async Task<string> GetStringAsync()
{
var text = await Task.Run(() =>
{
Task.Delay(2000);
return "helloWorld";
});
return text;
}
private async void HandleButton2Click(object sender, EventArgs e)
{
tbLog.Text += await GetStringAsync();
}