【问题标题】:Error in using await operator within an async lambda expression在异步 lambda 表达式中使用 await 运算符时出错
【发布时间】:2015-04-22 22:31:02
【问题描述】:

我正在尝试使用 Parallel.For 和异步等待将一些任意 GPS 数据(1.5 亿条记录)加载到 Azure 表存储中。但我在第一个等待语句中收到以下错误:

“await”运算符只能在异步 lambda 表达式中使用。考虑用 'async' 修饰符标记这个 lambda 表达式。

这是我的代码:

private static async Task GenerateGpsPointsForTruckAsync(int counter, CloudTableClient tableClient)
    {
        // Create a dummy VIN
        string vin = counter.ToString("D17");

        Random random = new Random();

        DateTime start = new DateTime(2010, 1, 1);
        int range = (DateTime.Today - start).Milliseconds;

        // Create the batch operation.
        TableBatchOperation batchOperation = new TableBatchOperation();

        // Prepare 10 batches of 100 GPS points
        Parallel.For(0, 10, i =>
        {
            for (int j = 0; j < 99; j++)
            {
                Location location = new Location(vin, start.AddDays(random.Next(range)).ToString());

                location.Coordinates = new GeoCoordinate(random.Next(30, 45), random.Next(75, 100));

                batchOperation.Insert(location);
            }

            await Task.Run(async () => 
            { 
                await LoadGpsPointsForTruckAsync(tableClient, batchOperation); 
            });
        });
    }

我在 Stack Overflow 上查看了一些解决方案,但它们似乎对我不起作用。

【问题讨论】:

  • 什么似乎不起作用?
  • 我认为您在 Parallel.For(0, 10, i =&gt; ... 行上创建的 lambda 上错过了 async 修饰符。你可以尝试在那里添加一个吗?
  • 你为什么要做await Task.Run(... 而不是简单的await LoadGpsPointsForTruckAsync(...);

标签: c# azure asynchronous lambda async-await


【解决方案1】:

您不能在 Parallel.For 中使用 async-await,因为它比 async 更早并且不等待它(您可能也不想这样做)。

如果您想创建在线程池上运行的多个任务,您可以通过多次调用Task.RunTask.WhenAll 来实现,这样您就可以通过await 来完成所有任务:

await Task.WhenAll(Enumerable.Range(0,10).Select(i => Task.Run(() => Foo(i))));

这适用于同步操作。如果它是异步的,除非您有理由这样做,否则您不应将其卸载到线程池中。您可以简单地调用该方法并等待结果:

await Task.WhenAll(Enumerable.Range(0,10).Select(i => FooAsync(i)));

【讨论】:

    【解决方案2】:

    Parallel.For 期望你也将它的 lambda 标记为 async,因为你的外部 await Task.Run

    Parallel.For(0, 10, async () => /* code */)
    

    但是,async-await 不能很好地与 Parallel 配合使用,因为它通过 Action 委托将其 lambdas 转换为 async void

    看来LoadGpsPointsForTruckAsync 本身就是异步的,你可以省去并行循环:

    var coordinateTasks = Enumerable.Range(0, 100).Select(_ => 
                {
                    Location location = new Location(vin, 
                                        start.AddDays(random.Next(range))
                                        .ToString())
                    {
                       Coordinates = new GeoCoordinate(random.Next(30, 45),
                                                       random.Next(75, 100));
                    }
    
                    batchOperation.Insert(location);
    
                    return LoadGpsPointsForTruckAsync(tableClient, batchOperation); 
                }
    
    await Task.WhenAll(coordinateTasks);
    

    【讨论】:

      猜你喜欢
      • 2016-02-08
      • 2014-01-02
      • 1970-01-01
      • 1970-01-01
      • 2014-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多