异步方法正在阻塞执行它的UI线程。

6

考虑以下Winform代码。当我点击按钮时,希望异步方法不会阻塞它所在的UI线程。

然而,我发现在异步方法调用期间按钮被冻结了... 如果是这样的话,异步方法有何意义呢?我很困惑。

namespace WindowsFrmAsyn
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        async private void button1_Click(object sender, EventArgs e)
        {
            int contentlength = await AccessTheWebAsync();
            tbResult.Text =
                        string.Format("Length of the downloaded string: {0}.", contentlength);

            Debug.WriteLine(tbResult.Text);
        }    

        async Task<int> AccessTheWebAsync()
        {
            Debug.WriteLine("Call AccessTheWebAsync");
            Thread.Sleep(5000);
            Debug.WriteLine("Call AccessTheWebAsync done");
            tbResult.Text = "I am in AccessTheWebAsync";
            return 1000;
        }
    }
}
3个回答

8
编译器警告已经明确告诉你发生了什么事情:由于你的async方法没有进行任何await操作,它会同步运行。 Thread.Sleep是一种同步操作;如果你想要模拟异步操作,请使用Task.Delay
async Task<int> AccessTheWebAsync()
{
  Debug.WriteLine("Call AccessTheWebAsync");
  await Task.Delay(5000);
  Debug.WriteLine("Call AccessTheWebAsync done");
  tbResult.Text = "I am in AccessTheWebAsync";
  return 1000;
}

2

目前在AccessTheWebAsync方法中缺少await,因为您没有等待任何东西,所以所有的代码都在主线程上运行。异步/等待不会使方法在不同的线程上运行,除了您等待的部分。

该方法必须像这样。

async Task<int> AccessTheWebAsync()
{
     // Console writeline
     await Task.Delay(seconds);
     // Console WriteLine.
     return value;
}

在异步方法中,等待之前和之后的所有内容都在调用该方法的同一线程上运行。可选地,您可以使用ConfigureAwait,它通常在库内部使用,以便等待之后的所有内容将发生在执行等待的同一线程上。
有关async/await的更多信息,请查看http://blogs.msdn.com/b/pfxteam/archive/2012/04/12/async-await-faq.aspx

1
当你编写这样的代码时:

当您编写此类代码时:

private async Task<int> DoStuffAsync()
{
    return 0;
}

这种方式是同步进行的,因为您没有使用await表达式。
请注意警告:
This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

根据警告提示,您可以通过以下方式进行更正:

private async Task<int> DoStuffAsync()
{
    return await Task.Run<int>(() =>
    {
        return 0;
    });
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接