Asynchronous programming in .net 4.5 with c#

57
Binu Bhasuran Microsoft MVP Visual C# Facebook http://facebook.com/codeno47 Blog http://proxdev.com/

Transcript of Asynchronous programming in .net 4.5 with c#

Page 1: Asynchronous programming in .net 4.5 with c#

Binu BhasuranMicrosoft MVP Visual C#

Facebook http://facebook.com/codeno47

Blog http://proxdev.com/

Page 2: Asynchronous programming in .net 4.5 with c#

Threading model was introduced in which release of .NET framework?1.01.12.03.53.5 SP1

2) Interlocked class introduced in which release of .NET framework?2.04.03.5 SP14.51.1

3) Can you stop an Asynchronous delegate?YesNoIt depends on implementation.It depends on .NET framework version.

4) By Default .NET application starts how many threads?123Depends on processor architecture.

Page 3: Asynchronous programming in .net 4.5 with c#

Asynchronous operations are operations which are initiated and then continue concurrently with the invoking code.When conforming to the .NET Task-Based Asynchronous Pattern (TAP), asynchronous methods return a task that represents the ongoing operation and allows waiting for its eventual outcome.Invoking and then asynchronously waiting for a task-returning method to complete is as simple as “await myAsyncMethod();”. The control flow is completely unaltered, and there are no callbacks in sight because the compiler takes care of creating and signing them up.

Page 4: Asynchronous programming in .net 4.5 with c#

Convert synchronous code into asynchronous code

Perform tasks without blocking the UI

Run concurrent tasks

Implement cancellation and polling features

Generate a DLL library that exposes asynchronous methods

Page 5: Asynchronous programming in .net 4.5 with c#

Initiation and completion of an asynchronous operation in the TAP are represented by a single method, and thus there is only one method to name. This is in contrast to the IAsyncResultpattern, or APM pattern, where BeginMethodNameand EndMethodName methods are required, and in contrast to the event-based asynchronous pattern, or EAP, where a MethodNameAsync is required in addition to one or more events, event handler delegate types, and EventArg-derived types. Asynchronous methods in the TAP are named with an “Async” suffix that follows the operation’s name, e.g. MethodNameAsync.

Page 6: Asynchronous programming in .net 4.5 with c#

The singular TAP method returns either a Task or a Task<TResult>, based on whether the corresponding synchronous method would return void or a type TResult, respectively. (If adding a TAP method to a class that already contains a method MethodNameAsync, the suffix “TaskAsync” may be used instead, resulting in “MethodNameTaskAsync”.)

Page 7: Asynchronous programming in .net 4.5 with c#

public class MyClass{

public IAsyncResult BeginRead(byte [] buffer, int offset, int count, AsyncCallback callback, object state);

public int EndRead(IAsyncResult asyncResult);}

Page 8: Asynchronous programming in .net 4.5 with c#

public class MyClass{

public void ReadAsync(byte [] buffer, int offset, int count);public event ReadCompletedEventHandler ReadCompleted;

}

public delegate void ReadCompletedEventHandler(object sender, ReadCompletedEventArgs eventArgs);

public class ReadCompletedEventArgs : AsyncCompletedEventArgs{

public int Result { get; }}

Page 9: Asynchronous programming in .net 4.5 with c#

TAP counterpart would expose the following single method:

public class MyClass

{

public Task<int> ReadAsync(byte [] buffer, intoffset, int count);

}

Page 10: Asynchronous programming in .net 4.5 with c#

The parameters to a basic TAP method should be the same parameters provided to the synchronous counterpart, in the same order.However, “out” and “ref” parameters are exempted from this rule and should be avoided entirely.Any data that would have been returned through an out or ref parameter should instead be returned as part of the returned Task<TResult>’s Result, utilizing a tuple or a custom data structure in order to accommodate multiple values.

Page 11: Asynchronous programming in .net 4.5 with c#

To expose a cancelable asynchronous operation, a TAP implementation provides an overload that accepts a CancellationToken after the synchronous counterpart method’s parameters. By convention, the parameter should be named “cancellationToken”.

Page 12: Asynchronous programming in .net 4.5 with c#

public Task<int> ReadAsync(byte [] buffer, int offset, int count, CancellationToken cancellationToken);

If the token has cancellation requested and the asynchronous operation is able to respect that request, the returned task will end in the TaskStatus.Canceled state; there will be no available Result and no Exception

Page 13: Asynchronous programming in .net 4.5 with c#

In the TAP, progress is handled through an IProgress<T> interface passed into the asynchronous method as a parameter named “progress”.

Providing the progress interface at the time of the asynchronous method’s invocation helps to eliminate race conditions that result from incorrect usage where event handlers incorrectly registered after the invocation of the operation may miss updates.

More importantly, it enables varying implementations of progress to be utilized, as determined by the consumer

Page 14: Asynchronous programming in .net 4.5 with c#

public Task<int> ReadAsync(

byte [] buffer, int offset, int count,

IProgress<int> progress);

Page 15: Asynchronous programming in .net 4.5 with c#

A single IProgress<T> implementation, Progress<T>, is provided built-in (more implementations may be provided in the future). The Progress<T> class is declared as follows:public class Progress<T> : IProgress<in T>{

public Progress();public Progress(Action<T> handler);protected OnReport(T value);public event ProgressEventHandler<T> ProgressChanged;

}

Page 16: Asynchronous programming in .net 4.5 with c#

public Task MethodNameAsync(…);

public Task MethodNameAsync(…, CancellationToken cancellationToken);

public Task MethodNameAsync(…, IProgress<T> progress);

public Task MethodNameAsync(…,

CancellationToken cancellationToken, IProgress<T> progress);

Page 17: Asynchronous programming in .net 4.5 with c#

Patterns and Types

From APM to Tasks

From Tasks to APM

Tasks and the Event-based Asynchronous Pattern (EAP)

Tasks and WaitHandles

From Tasks to WaitHandles

Page 18: Asynchronous programming in .net 4.5 with c#

The .NET Framework 1.0 saw the introduction of the IAsyncResult pattern, otherwise known as the Asynchronous Programming Model (APM) pattern, or the Begin/End pattern.

The .NET Framework 2.0 then brought with it the event-based asynchronous pattern (EAP).

The new TAP deprecates both of its predecessors, while at the same time providing the ability to easily build migration routines from the APM and EAP to TAP.

Page 19: Asynchronous programming in .net 4.5 with c#

The APM pattern relies on two corresponding methods to represent an asynchronous operation: BeginMethodName and EndMethodName. At a high-level, the begin method accepts as parameters to the method the same parameters that would be supplied to the MethodName synchronous method counterpart, as well as also accepting an AsyncCallback delegate and an object state

Page 20: Asynchronous programming in .net 4.5 with c#

The begin method then returns an IAsyncResult, which returns from its AsyncState property the object state passed to the begin method. When the asynchronous operation completes, the IAsyncResult’s IsCompletedwill start returning true, and its AsyncWaitHandle will be set.

Page 21: Asynchronous programming in .net 4.5 with c#

Additionally, if the AsyncCallback parameter to the begin method was non-null, the callback will be invoked and passed the same IAsyncResult that was returned from the begin method.

When the asynchronous operation does complete, the EndMethodName method is used to join with the operation, retrieving any results or forcing any exceptions that occurred to then propagate. There are further details around the IAsyncResult’s CompletedSynchronously property that are beyond the scope of this document; for more information, see MSDN

Page 22: Asynchronous programming in .net 4.5 with c#

Given the very structured nature of the APM pattern, it is quite easy to build a wrapper for an APM implementation to expose it as a TAP implementation. In fact, the .NET Framework 4 includes helper routines in the form of TaskFactory.FromAsync to provide this translation.

Page 23: Asynchronous programming in .net 4.5 with c#

Consider the .NET Stream class and its BeginRead/EndReadmethods, which represent the APM counterpart to the synchronous Read method:

public int Read(byte [] buffer, int offset, int count);

…public IAsyncResult BeginRead(

byte [] buffer, int offset, int count, AsyncCallback callback, object state);

public int EndRead(IAsyncResult asyncResult);

Page 24: Asynchronous programming in .net 4.5 with c#

Utilizing FromAsync, we can implement a TAP wrapper for this method as follows:

public static Task<int> ReadAsync(this Stream stream, byte [] buffer, int offset, int count)

{if (stream == null) throw new ArgumentNullException(“stream”);return Task<int>.Factory.FromAsync(stream.BeginRead,

stream.EndRead,buffer, offset, count, null);

}

Page 25: Asynchronous programming in .net 4.5 with c#

This implementation that utilizes FromAsync is effectively equivalent to the following:

public static Task<int> ReadAsync(this Stream stream, byte [] buffer, int offset, int count)

{if (stream == null) throw new ArgumentNullException(“stream”);var tcs = new TaskCompletionSource<int>();stream.BeginRead(buffer, offset, count, iar =>{

try { tcs.TrySetResult(stream.EndRead(iar)); }catch(OperationCanceledException) { tcs.TrySetCanceled(); }catch(Exception exc) { tcs.TrySetException(exc); }

}, null);return tcs.Task;

}

Page 26: Asynchronous programming in .net 4.5 with c#

For cases where existing infrastructure expects code to implement the APM pattern, it is also important to be able to be able to take a TAP implementation and use it where an APM implementation is expected.

Page 27: Asynchronous programming in .net 4.5 with c#

public static IAsyncResult AsApm<T>(this Task<T> task, AsyncCallback callback, object state)

{if (task == null) throw new ArgumentNullException(“task”);var tcs = new TaskCompletionSource<T>(state);task.ContinueWith(t =>{

if (t.IsFaulted) tcs.TrySetException(t.Exception.InnerExceptions)else if (t.IsCanceled) tcs.TrySetCanceled();else tcs.TrySetResult(t.Result);

if (callback != null) callback(tcs.Task);});return tcs.Task;

}

Page 28: Asynchronous programming in .net 4.5 with c#

Now, consider a case where we have a TAP implementation:

public static Task<string> DownloadStringAsync(Uri url);

And we need to provide an APM implementation:

public IAsyncResult BeginDownloadString(Uri url, AsyncCallback callback, object state);

public string EndDownloadString(IAsyncResult asyncResult);

Page 29: Asynchronous programming in .net 4.5 with c#

This is achievable with the following code:

public IAsyncResult BeginDownloadString(

Uri url, AsyncCallback callback, object state)

{

return DownloadStringAsync(url).AsApm(callback, state);

}

public string EndDownloadString(IAsyncResult asyncResult)

{

return ((Task<string>)asyncResult).Result;

}

Page 30: Asynchronous programming in .net 4.5 with c#

The event-based asynchronous pattern relies on an instance MethodNameAsync method which returns void, accepts the same parameters as the synchronous MethodName method, and initiates the asynchronous operation. Prior to initiating the asynchronous operation, event

handlers are registered with events on the same instance, and these events are then raised to provide progress and completion notifications. The event handlers are typically custom delegate types that utilize event argument types that are or that are derived from ProgressChangedEventArgs and AsyncCompletedEventArgs.

Page 31: Asynchronous programming in .net 4.5 with c#

public static Task<string> DownloadStringAsync(Uri url){

var tcs = new TaskCompletionSource<string>();var wc = new WebClient();wc.DownloadStringCompleted += (s,e) =>{

if (e.Error != null) tcs.TrySetException(e.Error);else if (e.Cancelled) tcs.TrySetCanceled();else tcs.TrySetResult(e.Result);

};wc.DownloadStringAsync(url);return tcs.Task;

}

Page 32: Asynchronous programming in .net 4.5 with c#

While not an asynchronous pattern per-se, advanced developers may find themselves utilizing WaitHandles and the ThreadPool’sRegisterWaitForSingleObject method to be notified asynchronously when a WaitHandle is set. We can wrap RegisterWaitForSingleObject to

enable a task-based alternative to any synchronous wait on a WaitHandle:

Page 33: Asynchronous programming in .net 4.5 with c#

public static Task WaitOneAsync(this WaitHandle waitHandle)

{

if (waitHandle == null) throw new ArgumentNullException("waitHandle");

var tcs = new TaskCompletionSource<bool>();

var rwh = ThreadPool.RegisterWaitForSingleObject(waitHandle,

delegate { tcs.TrySetResult(true); }, null, -1, true);

var t = tcs.Task;

t.ContinueWith(_ => rwh.Unregister(null));

return t;

}

Page 34: Asynchronous programming in .net 4.5 with c#

The Task class implements IAsyncResult, and its IAsyncResult implementation exposes an AsyncWaitHandle property which returns a WaitHandlethat will be set when the Task completes. As such, getting a WaitHandle for a Task is accomplished as follows:

WaitHandle wh = ((IAsyncResult)task).AsyncWaitHandle;

Page 35: Asynchronous programming in .net 4.5 with c#

We will create a WPF application to download a web page and find any link in the HTML. You will write the code in the old way by using synchronous calls and finally run the application to see the disadvantages of this way of programming

Page 36: Asynchronous programming in .net 4.5 with c#

In this exercise, you will create a very simple application that will download the HTML content of a web page and, using regular expressions, search through that content looking for any link. Then, you will display those links in a ListBox. You will build this application in two ways. First, you will build the application using synchronous code and examine the issues with this implementation. Second, you will modify that application to use the asynchronous code so you can see how this implementation addresses the issues with the first version of the application.

Page 37: Asynchronous programming in .net 4.5 with c#

try{

var response = new HttpClient().Get("http://msdn.microsoft.com"); string result =

response.EnsureSuccessStatusCode().Content.ReadAsString();

this.textBox1.Text = result;}catch (Exception){

MessageBox.Show(ex.ToString());}

Page 38: Asynchronous programming in .net 4.5 with c#

Notice the window is unresponsive and the button actually never disables because the UI is blocked while it downloads the web page.

Page 39: Asynchronous programming in .net 4.5 with c#

In the previous code, you are using the asynchronous version of the Get method, the GetAsync, which is a new method added by the .NET Framework 4.5 and has different signature since it returns aTask type object. A task represents an asynchronous operation which may complete at some point in the future.

Page 40: Asynchronous programming in .net 4.5 with c#

try{

var response = new HttpClient().GetAsync("http://msdn.microsoft.com");

string result = response.EnsureSuccessStatusCode().Content.ReadAsString();

this.textBox1.Text = result;...

Page 41: Asynchronous programming in .net 4.5 with c#

Adding the await keyword tells the compiler to asynchronously wait for the task returned from the method call. This means that the rest of the code will be executed as a callback only after the awaited method completes. Another thing to notice is that you do not need to change your try-catch block in order to make this work, as the exceptions that happen in the background or in the foreground will still be caught without any extra work using a handler provided by the framework.

Page 42: Asynchronous programming in .net 4.5 with c#

try{

var response = await new HttpClient().GetAsync("http://msdn.microsoft.com");

string result = response.EnsureSuccessStatusCode().Content.ReadAsString();

this.textBox1.Text = result;

Page 43: Asynchronous programming in .net 4.5 with c#

The await operator is applied to a task in an asynchronous method to suspend the execution of the method until the awaited task completes. The task represents ongoing work.

The asynchronous method in which await is used must be modified by the async keyword. Such a method, defined by using the asyncmodifier, and usually containing one or more await expressions, is referred to as an async method.

The task to which the await operator is applied typically is the return value from a call to a method that implements the Task-Based Asynchronous Pattern. Examples include values of type Task or Task<TResult>.

Page 44: Asynchronous programming in .net 4.5 with c#

An await expression does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the asyncmethod as a continuation on the awaited task. Control then returns to the caller of the asyncmethod. When the task completes, it invokes its continuation, and execution of the asyncmethod resumes where it left off.

Page 45: Asynchronous programming in .net 4.5 with c#

An await expression does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.

An await expression can occur only in the body of an immediately enclosing method, lambda expression, or anonymous method that is marked by an async modifier. The term await serves as a contextual keyword only in that context. Elsewhere, it is interpreted as an identifier. Within the method, lambda expression, or anonymous method, an await expression cannot occur in the body of a synchronous function, in a query expression, in the catch or finally block of an exception handling statement, in the block of a lock statement, or in an unsafe context.

Page 46: Asynchronous programming in .net 4.5 with c#

private async void button1_Click(object sender, EventArgs e){

// Call the method that runs asynchronously.string result = await WaitAsynchronouslyAsync();

// Call the method that runs synchronously.//string result = await WaitSynchronously ();

// Display the result.textBox1.Text += result;

}

Page 47: Asynchronous programming in .net 4.5 with c#

// The following method runs asynchronously. The UI thread is not// blocked during the delay. You can move or resize the Form1 window // while Task.Delay is running.public async Task<string> WaitAsynchronouslyAsync(){

await Task.Delay(10000);return "Finished";

}

// The following method runs synchronously, despite the use of async.// You cannot move or resize the Form1 window while Thread.Sleep// is running because the UI thread is blocked.public async Task<string> WaitSynchronously(){

// Add a using directive for System.Threading.Thread.Sleep(10000);return "Finished";

}

Page 48: Asynchronous programming in .net 4.5 with c#

The async modifier indicates that the method, lambda expression, or anonymous method that it modifies is asynchronous. Such methods are referred to as async methods.

An async method provides a convenient way to do potentially long-running work without blocking the caller's thread. The caller of an async method can resume its work without waiting for the asyncmethod to finish.

Page 49: Asynchronous programming in .net 4.5 with c#

Typically, a method modified by the async keyword contains at least one await expression or statement. The method runs synchronously until it reaches the firstawait expression, at which point it is suspended until the awaited task is complete. In the meantime, control is returned to the caller of the method. If the method does not contain an await expression or statement, then it executes synchronously. A compiler warning alerts you to any async methods that do not contain await.The async keyword is a contextual keyword. It is a keyword when it modifies a method, a lambda expression, or an anonymous method. In all other contexts, it is interpreted as an identifier.

Page 50: Asynchronous programming in .net 4.5 with c#

public async Task<int> ExampleMethodAsync(){

// . . .

// At the await expression, execution in this method is suspended and,// if AwaitedProcessAsync has not already finished, control returns// to the caller of ExampleMethodAsync.int exampleInt = await AwaitedProcessAsync();

// . . .

// The return statement completes the task. Any method that is // awaiting ExampleMethodAsync can now get the integer result.return exampleInt;

}

Page 51: Asynchronous programming in .net 4.5 with c#

An async method can have a return type of void, Task, or Task<TResult>. The method cannot declare any ref or out parameters, although it can call methods that have such parameters.The void return type is used primarily to define event handlers, where a void return type is required. An asyncmethod that returns void cannot be awaited.In other cases, you specify Task<T> for the return type of an async method if the return statement of the method specifies an operand of type T. You use Task if no meaningful value is returned when the method is completed. You can think of the Task return type as meaning "Task<void>." That is, a call to the method returns a Task, but when the Task is completed, any await expression that is awaiting the Task evaluates to void.

Page 52: Asynchronous programming in .net 4.5 with c#

// An event handler must return void.

private async void button1_Click(object sender, RoutedEventArgs e)

{

textBox1.Clear();

// SumPageSizesAsync returns a Task.

await SumPageSizesAsync();

textBox1.Text += "\r\nControl returned to button1_Click.\r\n";

}

Page 53: Asynchronous programming in .net 4.5 with c#

// The following async lambda expression creates an equivalent anonymous

// event handler.

button1.Click += async (sender, e) => {

textBox1.Clear();

// SumPageSizesAsync returns a Task.

await SumPageSizesAsync();

textBox1.Text += "\r\nControl returned to button1_Click.\r\n";

}

Page 54: Asynchronous programming in .net 4.5 with c#

// The following async method returns a Task<T>.private async Task<byte[]> GetByteArrayAsync(Uri currentURI){

// Declare an HttpClient object. HttpClient client = new HttpClient();

// The GetAsync method returns a Task(Of T), where T is an HttpResponseMessage.Task<HttpResponseMessage> httpRMTask = client.GetAsync(currentURI);

// Await httpRMTask evaluates to an HttpResponseMessage object.HttpResponseMessage httpRM = await httpRMTask;

// The following line can replace the previous two assignment statements.//HttpResponseMessage httpRM = await client.GetAsync(currentURI);

// Throw an exception if the HttpResponseMessage contains an error code.httpRM.EnsureSuccessStatusCode();

// Use ReadAsByteArray to access the content of the resource as a byte array.return httpRM.Content.ReadAsByteArray();

}

Page 55: Asynchronous programming in .net 4.5 with c#

Visual Studio 11 Developer Preview

http://msdn.microsoft.com/en-us/vstudio/hh127353

http://msdn.microsoft.com/en-us/library/hh156513(v=vs.110).aspx

Page 56: Asynchronous programming in .net 4.5 with c#
Page 57: Asynchronous programming in .net 4.5 with c#