C# 非并行运行的异步方法
我正在尝试理解async/Wait,看看是否需要在我的C# 非并行运行的异步方法,c#,asp.net,.net,asp.net-mvc,asp.net-mvc-4,C#,Asp.net,.net,Asp.net Mvc,Asp.net Mvc 4,我正在尝试理解async/Wait,看看是否需要在我的ASP.NETMVC5应用程序中使用异步调用 使用值填充视图模型时,我有以下几点: MyViewModel myViewModel = new MyViewModel(); myViewModel.Answer1 = await myService.CalculateAnswer1Async(); myViewModel.Answer2 = await myService.CalculateAnswer2Async(); 以及上述两种方法背
ASP.NETMVC5
应用程序中使用异步调用
使用值填充视图模型时,我有以下几点:
MyViewModel myViewModel = new MyViewModel();
myViewModel.Answer1 = await myService.CalculateAnswer1Async();
myViewModel.Answer2 = await myService.CalculateAnswer2Async();
以及上述两种方法背后的代码:
public async Task<int> CalculateAnswer1Async()
{
await Task.Delay(5000);
return 111;
}
public async Task<int> CalculateAnswer2Async()
{
await Task.Delay(6000);
return 222;
}
public async Task calculateanswerasync()
{
等待任务。延迟(5000);
返回111;
}
公共异步任务CalculateAnswer2Async()
{
等待任务。延迟(6000);
返回222;
}
据我所知,上述两个方法将依次执行,首先是CalculateAnswer1Async()
,然后是CalculateAnswer2Async()
。因此,完成此操作所需的最长时间应该是6秒左右(CalculateAnswer2Async()完成所需的时间)?但当我运行页面时,加载大约需要11秒,即5秒+6秒=11秒
有人能帮我澄清一下我做错了什么吗
myViewModel.Answer1 = await myService.CalculateAnswer1Async();
这将阻止当前线程,直到myService.CalculateAnswer1Async()完成。
事实上,当你使用wait关键字时,你是在告诉正在执行的线程:“嘿,wait unitl,我完成了这个操作,然后你就可以自由地执行下一行代码了。”
编辑:
而myService.calculateAnswerAsync();当myService.CalculateAnswer1Async()完成工作时,主线程可以返回到调用的某个对象。它将返回并转到方法的其余部分。在第一个方法完成后,您将启动第二个方法
CalculateAnswer2Async
,因为您等待第一个方法的结果
立即等待异步操作的结果只有在UI线程中才真正有用,因为它释放UI线程来做其他工作,而不是阻塞它。但它不会引入并发性
您要做的是先启动第一个方法,然后启动第二个方法,然后对两个结果调用wait
var result1 = myService.CalculateAnswer1Async();
var result2 = myService.CalculateAnswer2Async();
myViewModel.Answer1 = await result1;
myViewModel.Answer2 = await result2;
async
/await
本身并不引入并发性,而且完全有可能所有代码都同步运行。但是使用async
和await
可以让您从异步调用中获益,同时仍然拥有易于编写的代码,并且其行为与同步版本中的预期基本相同。在这种情况下,await会阻止方法的执行,直到异步方法完成为止,一个接一个地有效地运行它们
实际上,您要做的是并行运行它们:
MyViewModel myViewModel = new MyViewModel();
Task<int>[] tasks = new []
{
myService.CalculateAnswer1Async();
myService.CalculateAnswer2Async();
};
Task.WaitAll(tasks);
myViewModel.Answer1 = tasks[0].Result;
myViewModel.Answer2 = tasks[1].Result;
MyViewModel MyViewModel=newmyviewmodel();
任务[]任务=新任务[]
{
myService.CalculateAnswer1Async();
myService.CalculateAnswer2Async();
};
Task.WaitAll(任务);
myViewModel.Answer1=任务[0]。结果;
myViewModel.Answer2=任务[1]。结果;
当您等待时,您将暂停当前的异步
方法,直到该操作完成。线程被释放以执行其他工作,但该方法将不会继续执行,直到wait
完成。我在我的博客上有一个更详细的描述
如果要同时执行多个异步请求,则可以延迟等待
,直到所有任务都已启动。所以这是一个选择:
MyViewModel myViewModel = new MyViewModel();
var task1 = myService.CalculateAnswer1Async();
var task2 = myService.CalculateAnswer2Async();
myViewModel.Answer1 = await task1;
myViewModel.Answer2 = await task2;
使用任务稍微有效一些。当所有的(通常会产生clearar/cleaner代码):
如果所有操作都返回相同类型的值(int
,在本例中),则可以使用任务的结果来避免“虚假等待”。whalll
:
MyViewModel myViewModel = new MyViewModel();
var task1 = myService.CalculateAnswer1Async();
var task2 = myService.CalculateAnswer2Async();
var results = await Task.WhenAll(task1, task2);
myViewModel.Answer1 = results[0];
myViewModel.Answer2 = results[1];
如何将其更改为异步运行?它不会真正阻止当前线程,但您所使用的方法的可观察效果非常相似。它已异步运行,但恐怕您不知道并行编程和异步编程之间的区别。常规异步编程的最大区别在于,当您使用wait时,它不会阻塞当前线程,而只是命令等待。您似乎认为wait启动了一个新线程。情况正好相反:它等待现有的计算完成。
MyViewModel myViewModel = new MyViewModel();
var task1 = myService.CalculateAnswer1Async();
var task2 = myService.CalculateAnswer2Async();
var results = await Task.WhenAll(task1, task2);
myViewModel.Answer1 = results[0];
myViewModel.Answer2 = results[1];