我正在阅读一本有关C#书中的await和async关键字的章节。 主要是在解释这些方法调用,其中调用者使用await关键字等待被调用方法完成。
在这个简单的示例中,我认为这三个调用没有优势,但更重要的是没有区别。谁能解释这对应用程序流程有何影响?仅当调用线程是主GUI线程时有用吗?
static async Task Main(string[] args)
{
WriteText();
await WriteTextAsync();
WriteTextAsync().Wait();
}
static void WriteText()
{
Thread.Sleep(3_000);
Console.WriteLine("Hello");
}
static async Task WriteTextAsync()
{
await Task.Run(() =>
{
Thread.Sleep(3_000);
Console.WriteLine("Hello");
});
}
Ps:如果该方法的调用线程仍在等待该方法完成,那么它是否也可能是正常调用?
答案 0 :(得分:1)
据我了解,您的问题是
如果程序在 await WriteTextAsync()行中等待响应,那么好处是什么?
对于客户端应用程序,例如Windows Store,Windows桌面和Windows Phone应用程序,异步的主要好处是响应能力。这些类型的应用程序主要使用异步来保持UI响应。对于服务器应用程序,异步的主要好处是可伸缩性。
我将尝试从网络应用程序的角度进行解释。
假设您有一个Web应用程序依赖于外部资源(如数据库调用),则当客户端发起请求时,ASP.NET将使用其线程池线程之一并将其分配给该请求。由于是同步编写的,因此请求处理程序将同步调用该外部资源。这将阻塞请求线程,直到返回对外部资源的调用为止。图1展示了一个具有两个线程的线程池,其中一个线程被阻塞,等待外部资源。
图1同步等待外部资源
现在,如果第三个客户端同时请求,则线程池中没有线程可用于分配第三个请求。
在异步调用中,线程不会被卡住,而是会被释放并返回到线程池,这将有助于为第三个调用提供服务。
当请求服务器活动结束时,链接数据库调用结束,然后SynchronizationContext
恢复该调用并将休止符返回给客户端。
简单地类似于aync调用的下图
很多事情发生在引擎盖下。我是根据Async Programming : Introduction to Async/Await on ASP.NET和我的理解写的。强烈建议在使用async-wait
之前先有清楚的了解。
答案 1 :(得分:0)
您说WriteText()
时,WriteText()
将阻塞您当前的线程,直到它完成为止,因为它是同步的。
说出
编辑:根据Microsoft Docs,当您说await WriteTextAsync()
时,将产生一个新线程,并且不会阻塞不依赖于WriteTextAsync()
结果的计算。
await WriteTextAsync()
时,编译器会安排Main()
的其余部分在WriteTextAsync()
完成后执行。然后,应将控件返回给异步方法的调用方。但是Main()
的呼叫者是谁?因为它turns out,所以没有async Main()
-实际上是相同的同步Main()
-只是语法上的糖,没有在其中写入.Wait()
。因此,在这种情况下,此调用等效于WriteTextAsync().Wait()
!
最后,当您说WriteTextAsync().Wait()
时,您再次阻塞了当前线程并等待WriteTextAsync()
的结果。
答案 2 :(得分:0)
我将指的是:
//Call 1
WriteText();
//Call 2
await WriteTextAsync();
//Call 3
WriteTextAsync().Wait();
如果您要执行的是同步等待,则第一个调用没有任何问题。在控制台应用程序中,这是很正常的。
问题出现在具有UI的程序或需要最佳利用CPU资源的程序中,最常见的情况是Web应用程序。
使用await
的呼叫2执行异步等待WriteTextAsync
的结果。就其本身而言,这很好,这被认为是正常的。但是,WriteTextAsync
是一个很好的例子,您应该绝对不要:
static async Task WriteTextAsync()
{
// Let's create a Thread
await Task.Run(() =>
{
// just to block it completely, having it do nothing useful
Thread.Sleep(3_000);
Console.WriteLine("Hello");
});
}
相反,作者应该使用:
static async Task WriteTextAsync()
{
// Let's *not* create a new thread
await Task.Delay(3_000);
Console.WriteLine("Hello");
}
也许他们会进一步指出这一点,但是您没有给我们提供书名来知道这一点。
当调用方法不能为async
且必须调用async
方法时,必须执行第3号呼叫。
// Think that for some reason you cannot change the signature,
// like in the case of an interface, and an async void would make your code
// never complete correctly
static void Main(string[] args)
{
//Call 3
WriteTextAsync().Wait();
}
总的来说,我建议您找到一本更好的书。实际需要异步代码时,示例更易于理解。