I am trying to convert the following code to async/await:
long deletedBlobCount = 0;
Parallel.ForEach(BlobURLList, item => Interlocked.Add(ref deletedBlobCount, DeleteBlob(item)));
DeleteBlob(item) function returns 1 if blob was deleted, 0 otherwise. This is what my new code looks like (I am on .Net 4):
long deletedBlobCount = 0;
var deleteBlobTask = new List<Task>();
foreach (var item in BlobURLList)
{
deleteBlobTask.Add(t => { Interlocked.Add(ref deletedBlobCount, await DeleteBlobAsync(item))});
}
Compiler doesn't like await DeleteBlobAsync(item) here. This is the error: The 'await' operator can only be used within an async lambda expression. Consider marking this lambda expression with the 'async' modifier
What am I missing? Also, I can't make deletedBlobCount a class level variable (requirement for logging).
CodePudding user response:
Your code has several problems. That specific compiler error is complaining that you're using await inside a lambda function that is not marked async. It's expecting something like this:
deleteBlobTask.Add(async () => { Interlocked.Add(ref deletedBlobCount, await DeleteBlobAsync(item)); });
I also got rid of the t parameter, since you're not using it.
Notice that you were also missing a semicolon before the closing }. In a one-liner lambda, you can only omit the semicolon if you omit the braces, like this:
deleteBlobTask.Add(async () => Interlocked.Add(ref deletedBlobCount, await DeleteBlobAsync(item)) );
However, that still won't compile because the lambda expression is a Func<Task>: a function that returns a Task. Really what you want is a Task, or in other words, you want the result of running that function, not the function itself. As you have it, that function isn't being run.
To declare an inline function (a lambda) and run it at the same time, the syntax gets a little convoluted:
deleteBlobTask.Add(new Func<Task>(async () => Interlocked.Add(ref deletedBlobCount, await DeleteBlobAsync(item)))() );
Notice that you declare the Func<Task>, then put () at the end, just like you would any method call.
So.... it's complicated. Are you sure all this is that much better than just:
foreach (var item in BlobURLList)
{
deletedBlobCount = await DeleteBlobAsync(item);
}
CodePudding user response:
Try this in an async method:
long deletedBlobCount = 0;
var deleteBlobTask = new List<Task>();
foreach (var item in BlobURLList)
{
deleteBlobTask.Add(((Func<Task>)(async () => {
long sum = await DeleteBlobAsync(item);
Interlocked.Add(ref deletedBlobCount, sum);
}))());
}
