【问题标题】:async await makes my tasks slow while task.Start() runs them fastasync await 使我的任务变慢,而 task.Start() 快速运行它们
【发布时间】:2014-11-28 12:51:45
【问题描述】:

我正在运行 10k 个任务,每个任务将一批数据发送到 Azure 存储表。

如果我将下面的第一种方法与 async await 一起使用,它返回正在运行的任务,则任务执行的速度非常慢,并且从几秒爬升到 10、100 秒等变得越来越慢。

如果我使用下面的第二种方法返回新的正在运行的任务,它们运行得非常快!每个任务只需几十毫秒。

为什么会有如此巨大的差异?我错过了什么?

在我的任务创建结束时,我执行了一个简单的 Task.WaitAll(allTask​​s.ToArray())。

    private static async Task ExecuteBatch(TableBatchOperation tableBatchOperation, CloudTable cloudTable, TextWriter log)
{
    var stopwatch = Stopwatch.StartNew();
    await cloudTable.ExecuteBatchAsync(tableBatchOperation);
    stopwatch.Stop();
    log.WriteLine("Committed " + tableBatchOperation.Count + " records in " + stopwatch.Elapsed.TotalSeconds + " seconds.");
}

private static Task ExecuteBatch2(TableBatchOperation tableBatchOperation, CloudTable cloudTable, TextWriter log)
{
    return Task.Run(() =>
    {
        var stopwatch = Stopwatch.StartNew();
        cloudTable.ExecuteBatch(tableBatchOperation);
        stopwatch.Stop();
        log.WriteLine("Committed " + tableBatchOperation.Count + " records " + " in " + stopwatch.Elapsed.TotalSeconds + " seconds.");
    });
}

之后

【问题讨论】:

  • 在您的第二种方法中,您无需等待 cloudTable.ExecuteBatchAsync(tableBatchOperation); 完成,它只是触发然后继续。
  • 您的第二次尝试完全错误。您衡量的是任务的开始,而不是完成。
  • 是的,你是对的。我改为将其更改为 ExecuteBatch(同步版本),并且速度要慢得多。那是一个错字。

标签: c# azure async-await azure-table-storage


【解决方案1】:

因为当您使用await 时,您实际上是在“等待”结果,所以如果您阻止ExecuteBatch,它不会在ExcecuteBatchAsync 结束之前结束。

另一方面,ExecuteBatch2 不会“等待”任何东西。即使您阻止 ExecuteBatch2 响应,ExecuteBatchAsync 操作也会并行启动,ExecuteBatch2 会结束,尽管 ExecuteBatchAsync 启动的任务仍在运行。

更新:

1|   var stopwatch = Stopwatch.StartNew();
2|   await cloudTable.ExecuteBatchAsync(tableBatchOperation);
3|   stopwatch.Stop();
4|   log.WriteLine("Committed " + tableBatchOperation.Count + " records in " + stopwatch.Elapsed.TotalSeconds + " seconds.");

在第一种方法中,因为您正在等待,所以在第 2 行结束之前,您不会到达第 3 行。

但是在你的第二种方法中:

1|   var stopwatch = Stopwatch.StartNew();
2|   cloudTable.ExecuteBatchAsync(tableBatchOperation);
3|   stopwatch.Stop();
4|   log.WriteLine("Committed " + tableBatchOperation.Count + " records " + " in " + stopwatch.Elapsed.TotalSeconds + " seconds.");

你会立即从第 2 行到第 3 行,因为ExecuteBatchAsync 是并行发生的,没有任何东西会导致线程阻塞。如果你这样做cloudTable.ExecuteBatchAsync(tableBatchOperation).Wait(),你可能会得到与第一种方法相同的结果。

【讨论】:

  • 我知道这很简单,我知道它正盯着我看,但我仍然在努力寻找答案。 await 在那里使异步调用阻塞,并且仅在完成后返回。好的,但我仍然得到一长串在 Task.WaitAll() 调用中长时间阻塞的任务。第二个版本 ExecuteBatch2 的工作方式与我认为的第一个版本一样。
  • 我添加了更详细的解释。
猜你喜欢
  • 1970-01-01
  • 2016-12-01
  • 1970-01-01
  • 2012-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-09
相关资源
最近更新 更多