.net异步等待,我做错了什么

时间:2022-11-16 18:08:13

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