# Real World Async and Await Code Example

I have been looking everywhere to find good real world examples of the new Async and Await features in .net 4.5. I have come up with the following code to download a list of files and limit the number of concurrent downloads. I would appreciate any best practices or ways to improve/optimize this code.

We are calling the below code using the following statement.

await this.asyncDownloadManager.DownloadFiles(this.applicationShellViewModel.StartupAudioFiles, this.applicationShellViewModel.SecurityCookie, securityCookieDomain).ConfigureAwait(false);


We are then using events to add the downloaded files to an observablecollection (new thread safe version in .net 4.5) on the ViewModel.

public class AsyncDownloadManager
{

{

var urls = CreateUrls(fileIds);

foreach (var url in urls)
{
await throttler.WaitAsync();
{
try
{
HttpClientHandler httpClientHandler = new HttpClientHandler();
{
}

}
finally
{
throttler.Release();
}
}));
}
}

{
HttpClient client = new HttpClient(clientHandler);

try
{
HttpResponseMessage responseMessage = await client.GetAsync(url).ConfigureAwait(false);

{
}
else
{
return;
}

if (!Directory.Exists(Properties.Settings.Default.workingDirectory))
{
Directory.CreateDirectory(Properties.Settings.Default.workingDirectory);
}
using (FileStream filestream = new FileStream(downloadedFile.FileName, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
{
await filestream.WriteAsync(byteArray, 0, byteArray.Length);
}
}
catch(Exception ex)
{
return;
}
}

{
{
}
}

{
{
}

}

1. What is the affect of embedding Async / Await in other Async / Await methods? (Write filestream to disk inside an Async / Await method.
2. Is the ConfigureAwait(False) used properly or should we use it more liberally?
3. Should a httpclient be used for each separate task or should they share a singe one? 4. Are events a good way to "send" the downloaded file reference to the viewmodel?
4. Is the await Task.WhenAll(allTasks).ConfigureAwait(false); the best way to run all tasks concurrently limited by the SemaphoreSlim throttle.

First, some smaller things (in terms of the size of code changed):

1. I think you should use var more, especially when it's clear what type the object has, because you're just creating it.
2. You shouldn't read the response as a single byte array. Instead, you should use Streams where possible (it certainly is possible in your case), because they are more efficient.
3. Don't just ignore unknown exceptions. If there are some exceptions which you want to ignore (e.g. when a website returns 404), specify them explicitly.

The big thing I would change about your code is how you throttle your code and how you return the results. While throttling your code using Semaphore will work fine, I think you should let some library for asynchronous handling of collections do that for you. Such libraries include Rx and TPL Dataflow. Doing that will also let you avoid using an event, because your method will return “asynchronous collection” instead (IObservable<T> in Rx, ISourceBlock<T> in TPL Dataflow).

With TPL Dataflow, your code could look something like:

public ISourceBlock<DownloadedFile> DownloadFiles(string[] fileIds, string securityCookieString, string securityCookieDomain)
{
var urls = CreateUrls(fileIds);

// we have to use TransformManyBlock here, because we want to be able to return 0 or 1 items
async url =>
{
var httpClientHandler = new HttpClientHandler();
{
}

foreach (var url in urls)
block.Post(url);

block.Complete();

return block;
}

{
var client = new HttpClient(clientHandler);

try
{
HttpResponseMessage responseMessage = await client.GetAsync(url);

if (!Directory.Exists(Properties.Settings.Default.workingDirectory))
{
Directory.CreateDirectory(Properties.Settings.Default.workingDirectory);
}

using (var httpStream = await responseMessage.Content.ReadAsStreamAsync())
using (var filestream = new FileStream(
{
await httpStream.CopyToAsync(filestream, 4096);
}
}
// TODO: improve
catch (Exception ex)
{
}

}

• Thanks for the code. I tend to not use var when posting samples. I was thinking that stream was a much better way to consume than the bytearray, but I was worried about the async nature. I see how your code would work perfectly dealing with the streams. Finally - it seems like I need to really research Rx and TPL more. I had thought that they were somewhat obsolete with Async/Await, but it looks like I was mistaken. New releases for both. You would recommend TPL for this scenario? Nov 20 '12 at 1:03
• TPL is certainly not obsolete in any way by async, party because async is actually built on top of TPL (the Task type) and partly because they are doing different things (e.g. there is no direct async alternative to Parallel.ForEach()). But I was talking specifically about TPL Dataflow, which is new in .Net 4.5 and was written to take advantage of async. And Rx is not obsolete either, its uses are mostly different than plain async (though there is some overlap). Nov 20 '12 at 1:15
• Any reason you are not using this GetAsync overload with HttpCompletionOption.ResponseHeadersRead and then consume the response with ReadAsStreamAsync()? Dec 18 '13 at 16:43
• @G.Stoynev I just copied that code from the question. I don't actually know HttpClient that well. Dec 18 '13 at 17:23
• @AceInfinity I think your suggestions are good, but since a lot of them are modifying code that I copied from the question, I think you should post them as a separate review answer. Apr 25 '16 at 18:40

Sorry, I did not look thoroughly through your code, but regarding "good real world examples of the new Async and Await features":

Writing simple windows 8 store (ex-"Metro-style") application helped me greatly to understand and get used to async/await pattern.

Basically, in their new API everything that can be time-consuming (disk IO, network IO, etc) is now async. You just can't call it synchronously.

I think this is aimed to force us writing responsive apps which do not block UI thread. For example, you need to download a file and save it to disk, and display busy indicator in UI. In your ViewModel you then say something like:

void DoTheJob()
{
IsBusy=true;

• Note that for your code to compile, you would need to add the async modifier to your method. Also, it would be preferable if you changed its return type to Task, so that your method could be awaited in turn. Nov 13 '12 at 20:40