patterncsharpMinor
Downloading blobs asynchronously
Viewed 0 times
downloadingasynchronouslyblobs
Problem
We have a working implementation that is doing I/O operations, returning data from blobs in an async/await manner from Azure Blob Storage.
We have understood that the best way to read from blobs is to follow the async/await pattern and not using the
If you need any extra information about the code, I will happily provide it and hope to make it clearer.
//Method1 is not async, this is what is called from the controller
public IEnumerable Method1()
{
//Running the async method and returning the result from task
return Task.Run(() => GetDataAsync()).Result;
}
private async Task> GetDataAsync()
{
//There are multiple blob address where the data is held. The code creates, in parallel multiple tasks for each address.
//It returns tasks that will be run in Async pattern
var tasks = multipleBlobAddress.AsParallel.Select(blobAddress =>{
Task> task = GetDataFromBlobsAsync(blobAddress);
return task;
});
//Awaits all tasks to complete
var completedTasks = await Task.WhenAll>(tasks);
//Selects all the tasks and returns them. Each tasks has data.
return completedTasks.SelectMany(t => t);
}
private Task> GetDataFromBlobsAsync(string address)
{
//Opens the blob and reads from it
using (var blobStream = blobService.OpenRead(address))
{
//Deserialises the data read from the blob
data = service.DeserialiseData(blobStream);
}
return Task.FromResult>(data);
}We have understood that the best way to read from blobs is to follow the async/await pattern and not using the
AsParallel method (other suggestions are most welcomed). I have the following questions:- By creating tasks in parallel and then waiting for all of them to complete, do we lose any performance?
- What are the obvious areas where we got it wrong or we can improve and potentially increase the performance or make the code better to maintain/read?
- Are we correctly following the async / await pattern?
If you need any extra information about the code, I will happily provide it and hope to make it clearer.
Solution
There is never a need to do this:
Why start a new task and then synchronously wait with
Either use the synchronous api all the way from your controller down into the Azure Storage SDK or use the asynchronous one (with
return Task.Run(() => GetDataAsync()).Result;Why start a new task and then synchronously wait with
.Result? This is the sort of code that will bite you later when you find out that a synchronisation context can cause a deadlock. See Stephen Cleary's blog post on the subject of an async deadlock. Stephen's blog is an absolute gold mine of information on aysnc and await.Either use the synchronous api all the way from your controller down into the Azure Storage SDK or use the asynchronous one (with
async and await). Don't mix and match - that's a source of errors and also pointless. Aysnc is useful when there's something else the thread could be doing. E.g. in a web app that's serving requests. If the web app is blocked by .Result or Wait then there is no benefit and you should use the synchronous API.Code Snippets
return Task.Run(() => GetDataAsync()).Result;Context
StackExchange Code Review Q#145611, answer score: 6
Revisions (0)
No revisions yet.