根据我的理解,async和await所做的主要事情之一是使代码易于编写和阅读-但使用它们是否等于生成后台线程来执行长时间的逻辑?
我目前正在尝试最基本的例子。我内联添加了一些注释。你能给我解释一下吗?
// I don't understand why this method must be marked as `async`.
private async void button1_Click(object sender, EventArgs e)
{
Task<int> access = DoSomethingAsync();
// task independent stuff here
// this line is reached after the 5 seconds sleep from
// DoSomethingAsync() method. Shouldn't it be reached immediately?
int a = 1;
// from my understanding the waiting should be done here.
int x = await access;
}
async Task<int> DoSomethingAsync()
{
// is this executed on a background thread?
System.Threading.Thread.Sleep(5000);
return 1;
}
这个答案旨在提供一些特定于ASP.NET的信息。
通过在MVC控制器中使用async/await,可以提高线程池的利用率,并实现更好的吞吐量,如下文所述。
http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4
在web应用程序中看到大量的并发请求
启动或有突发负载(并发性突然增加),
使这些web服务调用异步将增加
应用程序的响应性。异步请求采用
处理同步请求所需的时间相同。例如,
如果一个请求进行了web服务调用,需要两秒钟才能完成
完成后,无论执行与否,请求都需要两秒钟
同步或异步。然而,在异步调用期间,
线程在运行时不会阻塞对其他请求的响应
等待第一个请求完成。因此,异步
请求阻止了请求队列和线程池的增长
调用长时间运行的操作的许多并发请求。
我想对此发表我的意见,如果任何其他答案包含我将解释的内容,我很抱歉,我读了大部分,但没有找到它,但我可能错过了一些东西。
我看到了很多错误的概念和很多好的解释,只是想解释一下异步与并行编程的区别,我相信这会让事情更容易理解。
当你需要做长时间的计算,处理器密集的工作,你应该选择使用并行编程,如果可能的话,以优化核心的使用。这将打开一些线程并同时处理一些事情。
假设你有一个数字数组,想要对每一个数字进行一些昂贵的长计算。平行是你的朋友。
异步编程在不同的用例中使用。
当你在等待一些不依赖于你的处理器的事情时,它用来释放你的线程,例如IO(写入和读取磁盘),当你执行IO时,你的线程什么都不做,当你等待一个昂贵的查询结果从DB返回时也是一样。
异步方法在线程等待很长时间返回结果时释放线程。这个线程可以被应用程序的其他部分使用(例如,在web应用程序中,它可以处理其他请求),也可以返回操作系统用于其他用途。
当您的结果完成时,相同的线程(或另一个线程)将返回给您的应用程序以继续处理。
在像。net这样的多线程环境中,异步编程不是强制性的(但是个很好的实践),在web应用程序中,其他线程将响应新请求,但如果你是在像nodejs这样的单线程框架中,这是强制性的,因为你不能阻塞你唯一的线程,否则你将无法回答任何其他请求。
总而言之,长处理器密集型计算将从并行编程中受益更多,而不依赖于处理器的长等待时间,如IO或DB查询或对某些API的调用将从异步编程中受益更多。
这就是为什么Entity Framework有一个async api来保存、列表、查找等等…
记住async/await与wait或waitAll不同,上下文不同。Async/await释放线程,是异步编程。wait / waitAll阻塞所有线程(它们没有被释放)来强制并行上下文中的同步…不同的东西…
希望这对某些人有用…
这里的答案可以作为await/async的一般指导。它们还包含一些关于await/async如何连接的细节。我想和大家分享一些在使用这个设计模式之前应该知道的实践经验。
术语“await”是字面意义上的,所以无论您在哪个线程上调用它,都将在继续之前等待该方法的结果。在前台线程上,这是一个灾难。前台线程承担了构建应用程序的负担,包括视图、视图模型、初始动画,以及其他任何与这些元素捆绑在一起的东西。所以当你等待前台线程时,你会停止应用程序。当什么都没有发生时,用户会一直等待。这提供了一种消极的用户体验。
你当然可以使用各种方法来等待后台线程:
Device.BeginInvokeOnMainThread(async () => { await AnyAwaitableMethod(); });
// Notice that we do not await the following call,
// as that would tie it to the foreground thread.
try
{
Task.Run(async () => { await AnyAwaitableMethod(); });
}
catch
{}
这些注释的完整代码在https://github.com/marcusts/xamarin-forms-annoyances。参见名为AwaitAsyncAntipattern.sln的解决方案。
GitHub网站还提供了关于此主题的更详细讨论的链接。