Tuesday, 24 March 2015

ASP.NET Tips #30 - Use ConfigureAwait to avoid thread hopping, especially in library code

One of the most amazing thing about using async/await keywords for async and background processes is that you don't have to do anything special to be able to interact with the UI thread.

For example, if you trigger an async operation on the UI thread, then interact with a TextBox after the code returns, the .NET framework will automatically marshal the continuation back to the UI thread for you behind the scenes.

This is often very helpful, because you need to interact with the UI thread, but there are other times where you really are thread agnostic. In those cases it is important to use ConfigureAwait to set ContinueOnCapturedContext to false. This ensures that the .NET runtime doesn't have to go through the effort of resuming your method on the thread that called it. In general, this prevents a lot of back-and-forth thread hopping, but in some cases it can be even more helpful

Consider this example using ConfigureAwait:

byte [] buffer = new byte[0x1000];
int numRead;
while((numRead = await source.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false)) > 0)
{
   await source.WriteAsync(buffer, 0, numRead).ConfigureAwait(false);
}

This code reads an input source in small blocks. If we were working with a large input stream, we could easily have 10, 20, or even more different await cycles. Each cycle through is at least two async calls, with two sets of callbacks to the calling thread. By using ConfigureAwait(false), the total time to execution is much lower and we truly get the best performance out of async.

No comments :

Post a comment