我正在尝试使用 Parallel.For 和异步等待将一些任意 GPS 数据(1.5 亿条记录)加载到 Azure 表存储中。但是我在第一个等待语句中收到以下错误:
"await"运算符只能在异步 lambda 表达式中使用。考虑使用"异步"修饰符标记此 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);
});
});
}
我查看了一些关于堆栈溢出的解决方案,但它们似乎对我不起作用。
在Parallel.For
中使用 async-await,因为它比 async 旧并且不等待它(你可能也不想)。
如果要创建在线程池上运行的多个任务,可以通过多次调用Task.Run
Task.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)));
Parallel.For
希望您也将其 lambda 标记为 async
,因为您的外部await Task.Run
:
Parallel.For(0, 10, async () => /* code */)
但是,async-await
不能很好地与Parallel
配合使用,因为它通过Action
委托将其 lambda 转换为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);