简体   繁体   中英

async method is blocking UI thread on which it is executing

Consider the following codes in Winform. When I clicked the button, I was expecting that the async method should not block UI thread on which it was executing.

However, I found out that button was frozen during async method calling... If true, what is the point of async method? I am confused.

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

The compiler warning tells you exactly what's going on: since your async method does not ever await , it will run synchronously.

Thread.Sleep is a synchronous operation; if you want to fake an asynchronous operation, use 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;
}

Currently you're lacking await in the AccessTheWebAsync because you do not await anything so all code runs on the main thread. Async/await doesn't make the method run on a different thread except the part that you await.

The method must be something like this.

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

So everything before and after an await inside the async method is run on the same thread the method has been called. Optionally you can use ConfigureAwait that is commonly used inside libraries so that everything after the await will occur at the same thread the await has been done.

Checkout http://blogs.msdn.com/b/pfxteam/archive/2012/04/12/async-await-faq.aspx for some more information about async/await.

When you write such code:

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

This way you are doing things synchronously, because you are not using await expression.

Pay attention to the warning:

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.

Based on the warning suggestion you can correct it this way:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM