Reputation: 1625
I am trying to load some arbitrary GPS data (150 million records) into Azure Table storage using Parallel.For and async await. But I am getting the following error in the first await statement:
The 'await' operator can only be used within an async lambda expression. Consider marking this lambda expression with the 'async' modifier.
Here is my code:
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);
});
});
}
I looked at a few solutions on Stack Overflow but they don't seem to be working for me.
Upvotes: 1
Views: 3579
Reputation: 149628
Parallel.For
is expecting you to mark its lambda as async
as well, because of your outter await Task.Run
:
Parallel.For(0, 10, async () => /* code */)
But, async-await
doesn't play well with Parallel
as it converts it's lambdas to async void
via an Action
delegate.
It seems that LoadGpsPointsForTruckAsync
by itself is async, you can save yourself the parallel loop:
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);
Upvotes: 0
Reputation: 116636
You can't use async-await inside Parallel.For
as it's older than async and doesn't await it (you probably don't want to either).
If you want to create multiple tasks that run on the thread pool you can do that with multiple calls to Task.Run
with Task.WhenAll
so you can await
for all of them to complete:
await Task.WhenAll(Enumerable.Range(0,10).Select(i => Task.Run(() => Foo(i))));
That's appropriate when the operation is synchronous. If it's asynchronous you shouldn't offload it to the thread pool unless you have a reason to do so. You can simply call the method and await the results:
await Task.WhenAll(Enumerable.Range(0,10).Select(i => FooAsync(i)));
Upvotes: 3