异步和等待需要澄清

时间:2013-09-30 13:04:57

标签: c# async-await

我阅读了许多关于异步和等待的文章(主要来自msdn - 实际上这很好)。还有一个问题困扰着我,我找不到答案。

如果任务上有await语句,则控件将返回其调用者,直到在调用者中再次等待它为止。在这种情况下,这个耗时的任务是在一个单独的线程中执行的吗?如果没有,那么它是如何与主线程并行执行的。

async Task<string> GetContentsAsync()
{
    int sample = 0;
    HttpClient client = new HttpClient();
    Task<string> contents = client.GetStringAsync("http://www.microsoft.com");
            
    string data = await contents;
    return data;
}

我希望我的问题很明确。

2 个答案:

答案 0 :(得分:5)

  

在这种情况下,这个耗时的任务是在一个单独的线程中执行的吗?

有两种任务。有些Task有代码要执行,它们在某个线程上运行。其他Task执行代码;他们只代表未来的一些事件。

“事件任务”由async使用 lot ,特别是在I / O场景中。在您的示例中,您正在执行HTTP GET。 GetStringAsync将发送HTTP请求,然后返回在收到响应时完成的“事件任务”。当HTTP请求正在运行并由服务器处理时,客户端没有代码来执行该请求。因此,不需要任何线程,也没有使用任何线程。

另请参阅我的回答here

答案 1 :(得分:4)

这取决于任务的创建方式,但不是,任务不会在一个单独的线程上自动执行 。一些辅助方法,例如Task.Run,可以帮助您确保将任务放在单独的线程上(在这种情况下是线程池)。

请记住,GUI应用程序,特别是WinForms,运行所谓的事件循环。在WinForms中,这发生在Application.Run调用之后。此事件循环接收点击等事件并调用您的处理程序。该循环执行的线程称为“GUI线程”。在WinForms中,它是创建所有控件的线程,因此也是允许触摸这些控件的唯一线程。

在方法上使用async修饰符创建任务时,该代码也会安排通过此事件循环执行。它刚排队等候。就像好的旧Invoke电话一样。因此,一旦您的事件处理程序返回,最终事件循环将进入该排队任务,执行它,然后执行await之后的其余方法。这里没有并行性。

但是,还有其他方法可以创建任务;调用async方法只是一种方法。 Task.Run创建放在不同线程上的任务。您在示例中显示的GetStringAsync实际上将与调用该任务的任何线程并行运行。