【问题标题】:Real advantages of Async-Await?Async-Await 的真正优势?
【发布时间】:2012-10-01 12:52:09
【问题描述】:

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

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

主要方法

List<Task<string>> tasksList = new List<Task<string>>();
List<int> asyncThreads = new List<int>();
List<int> tplThreads = new List<int>();
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());

将呼叫异步和同步到服务

static async Task<string> GetNameFromServiceAsync(string name, List<int> 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<string> GetNameFromService(string name, List<int> threads)
{

    var task = Task<string>.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 ,那么它将消耗更少的线程。这有多正确?如果不是,那么提出这种比较的正确方向是什么?

问。当我正在学习 async - await 时,我想通过某种比较和可靠的代码来证明它的价值。

【问题讨论】:

  • 你的问题到底是什么?
  • 通过使用 async - await 我们可以获得内存优势(将使用更少的资源)。这是我从之前的问题中得到的,或者我所理解的,我想知道这就是它的答案。我想通过使用 async-await 来询问可扩展性优势。是否符合我的结论?
  • 一个重要的优势是明确的,即用户在编写同步代码时不能说他们遇到了异步问题。
  • 微基准在评估这样的事情方面通常很差,恕我直言。

标签: c# performance async-await


【解决方案1】:

客户端async(与同步代码相比)通常会以轻微的内存成本提高响应速度。

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

这两个都是极端的概括,当然在某些情况下它们是错误的。

更新:

我的观察得出结论,如果我们使用 Async-Await ...,那么它将消耗更少的线程。

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

在学习 async - await 时,我想通过某种比较和可靠的代码来证明它的价值。

asyncawait 是编译器转换。它们使编写异步程序变得更容易——仅此而已。

如果您将它们与同步代码进行比较,您通常会发现响应能力和/或可扩展性有所提高。如果您将它们与现有的异步代码进行比较,那么它们的效率通常低,但在代码可维护性方面足以弥补这一点。

【讨论】:

  • 谢谢斯蒂芬。我已经更新了我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-24
  • 2022-01-19
  • 2016-08-09
  • 2020-04-20
  • 2016-05-30
  • 2020-03-25
  • 1970-01-01
相关资源
最近更新 更多