ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

await keyword blocks main thread

2022-07-05 16:35:30  阅读:143  来源: 互联网

标签:Task blocks thread await DoSomethingAsync async main method


await keyword blocks main thread

问题

So I have the following code

private async void button1_Click(object sender, EventArgs e)
{
    await DoSomethingAsync();

    MessageBox.Show("Test");
}

private async Task DoSomethingAsync()
{
    for (int i = 0; i < 1000000000; i++)
    {
        int a = 5;
    }; // simulate job

    MessageBox.Show("DoSomethingAsync is done");

    await DoSomething2Async();
}

private async Task DoSomething2Async()
{
    for (int i = 0; i < 1000000000; i++)
    {
        int a = 5;
    } // simulate job

    MessageBox.Show("DoSomething2Async is done");
}

Until both MessageBoxes are shown the main thread is block (I mean the application itself is frozen). There is obviously something wrong with my code and I can't figure out what. I've never used async/await before. this is my first attempt.

EDIT:

Actually what i want to do is to start Execution of DoSomethingAsync asynchronously so that when button is clicked the MessageBox.Show("Test"); would execute even though the DoSomethingAsync is incomplete.

 

@Tobberoth, no, it's not what await does. It returns to the caller, and resumes the method when the awaited task it complete. – Thomas Levesque Nov 6, 2013 at 13:57

 

回答1

I think you misunderstand what async means. It doesn't mean that the method runs in another thread!!

An async method runs synchronously until the first await, then returns a Task to the caller (unless it's async void, then it returns nothing). When the task that is being awaited completes, execution resumes after the await, usually on the same thread (if it has a SynchronizationContext).

In your case, the Thread.Sleep is before the first await, so it's executed synchronously, before control is returned to the caller. But even if it was after the await, it would still block the UI thread, unless you specifically configured the the awaiter not to capture the synchronization context (using ConfigureAwait(false)).

Thread.Sleep is a blocking method. If you want an async equivalent, use await Task.Delay(3000), as suggested in Sriram Sakthivel's answer. It will return immediately, and resume after 3 seconds, without blocking the UI thread.

It's a common misconception that async is related to multithreading. It can be, but in many cases it's not. A new thread is not implicitly spawned just because the method is async; for a new thread to spawn, it has to be done explicitly at some point. If you specifically want the method to run on a different thread, use Task.Run.

 

回答2

You should note that methods marked with async will no longer behave async when it lacks await. You'd have got compiler warning about this.

Warning 1 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.

You should give attention to those warnings.

Do it asynchronously. When I say asynchronous it is really asynchronous not synchronous job in another thread. Use Task.Delay which is really asynchronous. Use Task.Run for some time consuming job which is CPU bound.

private async void button1_Click(object sender, EventArgs e)
{
   await DoSomethingAsync();
}

private async Task DoSomethingAsync()
{
    await Task.Delay(3000); // simulate job

    MessageBox.Show("DoSomethingAsync is done");

    await DoSomething2Async();
}

private async Task DoSomething2Async()
{
    await Task.Delay(3000); // simulate job

    MessageBox.Show("DoSomething2Async is done");
}

 

回答3

You're not doing anything asynchronously. Try:

await Task.Run(() => Thread.Sleep(3000))

When you await a method, what you are effectively doing is providing a callback, with the code that follows it as what is executed once it finishes (in previous incarnations of async you actually had to set this up yourself). If you don't await anything then the method isn't really an asynchronous one.

For further information, you could do worse than looking here:

http://msmvps.com/blogs/jon_skeet/archive/2011/05/08/eduasync-part-1-introduction.aspx

Following your edit; try this:

public void MyMessageBox()
{
  var thread = new Thread(() =>
  {
      MessageBox.Show(...);
  });
  thread.Start();
}

Although, are you sure it's really a message box you want? I would have thought a status bar / progress bar update would fit better.

 

标签:Task,blocks,thread,await,DoSomethingAsync,async,main,method
来源: https://www.cnblogs.com/chucklu/p/16446918.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有