3

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

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

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

我希望我的问题很清楚。

4

2 回答 2

5

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

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

“事件任务”被大量使用async,尤其是在 I/O 场景中。在您的示例中,您正在执行 HTTP GET。GetStringAsync将发送 HTTP 请求,然后返回一个在收到响应时完成的“事件任务”。当 HTTP 请求在运行中并由服务器处理时,客户端没有为该请求执行的代码。所以不需要线程,也没有使用线程。

另请参阅我的答案here

于 2013-09-30T13:33:21.957 回答
4

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

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

当您在方法上使用修饰符创建任务时async,该代码也计划通过此事件循环执行。它只是排队。就像过去的好Invoke电话一样。因此,一旦您的事件处理程序返回,事件循环最终会到达排队的任务,执行它,然后执行await. 这里没有并行性。

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

于 2013-09-30T13:07:51.523 回答