我使用async关键字编写了一个方法,但无法理解它的结果,以及它无法正常工作的原因:
static async void ExampleWithValueReturned_Async(Stopwatch sw, SlowOperation opr1, SlowOperation opr2)
{
Console.WriteLine("Started processing ASYNC. Start: {0}", sw.Elapsed);
sw.Start();
Console.WriteLine("2 Step0: {0}", sw.Elapsed);
var sum1_2 = await Task<double>.Factory.StartNew(() => opr1.PerformSlowOperation(1, true));
Console.WriteLine("2 Step1: {0}", sw.Elapsed);
var sum2_2 = await Task<double>.Factory.StartNew(() => opr2.PerformSlowOperation(1, true));
Console.WriteLine("2 Step2: {0}", sw.Elapsed);
Console.WriteLine("Operation 1 gave sum: {0}", sum1_2.ToString("0.##"));
Console.WriteLine("Operation 2 gave sum: {0}", sum2_2.ToString("0.##"));
Console.WriteLine("Stopped processing ASYNC. Stop: {0}", sw.Elapsed);
sw.Stop();
sw.Reset();
Console.WriteLine("");
}
由于PerformSlowOperation将并行运行,因此我希望它的运行速度是内联处理速度的两倍。我的期望是生成sum1_2和sum2_2将同时发生,而基于秒表日志的结果分析表明,两个值的处理方式与内联处理案例完全相同。两种情况下的总时间也相同。为什么会这样?
答案 0 :(得分:5)
C#await
关键字正好与单词所说的相同,它等待函数在继续执行下一行之前完成执行。如果您没有使用await
关键字,那么它将在后台运行并继续执行其余代码,但是这不允许您对结果执行任何操作。
要并行运行这两个任务,您需要明确声明等待所有任务完成后再继续而不是等待每个任务。
Task t1 = Task<double>.Factory.StartNew(() => opr1.PerformSlowOperation(1, true));
Task t2 = Task<double>.Factory.StartNew(() => opr2.PerformSlowOperation(1, true));
await Task.WhenAll(t1,t2);
var sum1_2 = t1.Result;
var sum2_2 = t2.Result;
上面的代码将一直等到两个完成,然后并行运行它们,然后再继续使用其余的代码。
关键字存在的原因不是启用并行任务,而是让应用程序在执行其余代码之前等待单个异步方法完成。它在ASP.NET中非常有用,其中长时间运行的任务会浪费线程,使用await
告诉ASP.NET它可以放弃对另一个请求的线程控制,直到前一个长时间运行的请求为止。任务完成然后当它完成时让它回来控制线程。