Async-Await的真正优势是什么?

早些时候我发布了与在客户端或服务中应用Async-Await相关的问题。 在继续讨论这个问题之前,请先阅读这个问题,因为它与问题紧密相关。

基于答案,我已经测试了C#4.0(TPL)和C#5.0(Async – Await)的代码。 我使用服务提供的方法的异步和同步版本调用服务,并比较每种情况下使用的线程数。 以下是我用于测试所用资源的代码:

主要方法

List<Task> tasksList = new List<Task>(); List asyncThreads = new List(); List tplThreads = new List(); Stopwatch watch = new Stopwatch(); watch.Start(); // Call the Async version of the method for (int i = 0; i < 500; i++) { tasksList.Add(GetNameFromServiceAsync("Input" + i.ToString(), asyncThreads)); } Task.WaitAll(tasksList.ToArray()); watch.Stop(); foreach (var item in asyncThreads.Distinct()) { Console.WriteLine(item); } Console.WriteLine("(C# 5.0)Asynchrony Total Threads = " + asyncThreads.Distinct().Count()); Console.WriteLine(watch.ElapsedMilliseconds.ToString()); watch.Restart(); tasksList.Clear(); // Call the normal method for (int i = 0; i < 500; i++) { tasksList.Add(GetNameFromService("Input" + i.ToString(), tplThreads)); } Task.WaitAll(tasksList.ToArray()); watch.Stop(); foreach (var item in tplThreads.Distinct()) { Console.WriteLine(item); } Console.WriteLine("(C# 4.0)TPL Total Threads" + tplThreads.Distinct().Count()); Console.WriteLine(watch.ElapsedMilliseconds.ToString()); 

异步和同步CAlls到服务

 static async Task GetNameFromServiceAsync(string name, List threads) { Console.WriteLine(" Start Current Thread : " + System.Threading.Thread.CurrentThread.ManagedThreadId); var task = await client.GetNameAsync(name); threads.Add(System.Threading.Thread.CurrentThread.ManagedThreadId); // Console.WriteLine("End GetNameFromServiceAsync Current Thread : " + System.Threading.Thread.CurrentThread.ManagedThreadId); return task; } static Task GetNameFromService(string name, List threads) { var task = Task.Factory.StartNew(() => { threads.Add(System.Threading.Thread.CurrentThread.ManagedThreadId); // Console.WriteLine("GetNameFromService Current Thread : " + System.Threading.Thread.CurrentThread.ManagedThreadId); return client.GetName(name); }); return task; } 

现在我已经研究了答案并找出了以下结果:

  • 如果我对服务进行500次调用,它只使用4-5个线程。
  • TPL调用大约44-45个线程。
  • 异步呼叫的时间大约是17-18秒
  • TPL呼叫的时间大约为42-45秒。

我希望对我的调查结果有一些反馈,以便它对其他社区成员也有用。 这是我之前问题的答案吗?

编辑

问:我的观察结论是,如果我们使用Async-Await而不是TPL的Task.Factory.startNew,那么它将消耗较少的线程。 这是怎么回事? 如果没有,那么什么是与这些比较相关的正确方向?

问:因为我正在学习异步 – 等待,我想通过某种比较和可靠的代码来certificate它的价值。

客户端async (与同步代码相比)通常以较低的内存成本提高响应能力。

服务器端async (与同步代码相比)通常通过减少内存/线程使用来提高可伸缩性。 这些优点也适用于客户端async (与multithreading代码相比)。

这两者都是极端概括,当然也存在错误的情况。

更新:

我的观察结论是,如果我们使用Async-Await …,那么它将消耗较少的线程。

async / await启用可维护的异步代码。 它们本身与创建线程没有任何关系。 但是,它们通常与Task.Run (或Task.Factory.StartNew )一起使用来创建后台任务。

因为我正在学习异步 – 等待,我想通过某种比较和可靠的代码certificate它的价值。

asyncawait是编译器转换。 它们使编写异步程序变得更容易 – 就是这样。

如果将它们与同步代码进行比较,那么您通常会看到改进的响应性和/或可伸缩性。 如果将它们与现有的异步代码进行比较,那么它们的效率通常会稍微低一些,但在代码可维护性方面可以弥补这一点。