Showing posts with label ASynchDelegate. Show all posts
Showing posts with label ASynchDelegate. Show all posts

Wednesday, February 23, 2011

WPF - ASynchronous Function using Observable.ToASync [Rx ASynchronous Delegate] - Part # 2

This is the second part of our discussion about how we can execute the similar functionality as provided by asynchronous anonymous delegates in .net. In previous post we discuss how we can mimic the functionality provided by Func<...> delegate.

http://shujaatsiddiqi.blogspot.com/2011/02/wpf-asynchronous-function-using.html

In this post we will discuss about Action<...> delegate. As we know that we can not return any value from this compared to Func<...> delegate. As we know that .net provides 16 different generic overloads of Action<...> delegates in order to accommodate delegates for methods having up to 16 parameters. Similarly, 16 different overloads of Observable.ToAsync have been provided.

Let us add this method to our class:

[DebuggerStepThrough]
private void ProcessOperandsFireAndForget(decimal operand1, decimal operand2)
{
Thread.Sleep(5000);
if (operand1 <= 0 || operand2 <= 0)
{
throw new System.Exception("Exception generated");
}
}

Since it returns void, we can use Action delegate for this. In Reactive Extension we can use Observable.ToAsync for this method. It just producing a delay of 5 seconds. If any of the operands are zero or negative, it is resulting in an exception with message "Exception generated".

In order to run this we add another button on the window. The handler for Click event for the button can be as follows:

private void btnFireAndForget_Click(object sender, RoutedEventArgs e)
{
decimal operand1 = Decimal.Parse(this.textBoxOperand1.Text);
decimal operand2 = Decimal.Parse(this.textBoxOperand2.Text);

Observable.ToAsynclt;decimal, decimal>(ProcessOperandsFireAndForget, Scheduler.TaskPool)(operand1, operand2)
.ObserveOnDispatcher()
.Subscribe<Unit>(
(result) => { ; },
(ex) => this.Background = Brushes.Red,
() => this.Background = Brushes.Green);

}

Before running this code, let me explain the expected behavior. Basically you should be expecting the same behavior as of a method which actually returns a value. We can see that from marble diagram:

Graceful method execution:



Exception in method execution:


Now one thing is of interest which you might have already noticed. It is about OnNext message. Since OnNext passes some data in its argument, what data runtime would be passing in this as this method has void return type. Just to clarify this, I have used a generic overload of Subscribe method. See Unit type there? Basically is a new IEquatable struct provided in .net framework. Basically the message is generated. For methods with no return types, OnNext messages are generated with this type.



IScheduler support for Observable.ToAsync:
As I have told you that various overloads have been provided for Observable.ToAsync have been provided to accommodate all different overloads of Func and Action delegates. Make it at least double. Basically with each overload provided to support a particular number of arguments, one overload is provided to support an IScheduler so that we could decide which IScheduler to use to run this asynchronous code. Using these overloads we can specify which Scheduler we want to use to execute the method. Whatever thread is used to execute the method, would be the same thread on which OnNext, OnCompleted and OnError messages are generated.

Note:
We can also execute methods without any parameters with / without any return type using Observable.ToAsync. It would be following the same marble diagrams as presented in this post.

Download Code:

Tuesday, February 22, 2011

WPF - ASynchronous Function using Observable.ToASync [Rx ASynchronous Delegate] - Part # 1

This is the first part of our discussion about asynchronous method execution using Reactive Extension. The second part of this discussion can be found here:

http://shujaatsiddiqi.blogspot.com/2011/02/wpf-asynchronous-function-using_23.html

In this post we discuss how we can execute a method asynchronously using the features provided in Reactive Extensions Rx. We discussed the usage of asynchronous delegate in a WPF application in the following post:

http://shujaatsiddiqi.blogspot.com/2010/12/asynchronous-delegate-exception-
model.html

This is basically the similar concept in Rx.

<Window x:Class="WpfApp_AsynchObserver.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBox Height="27" HorizontalAlignment="Left" Margin="138,22,0,0"
Name="textBoxOperand1" VerticalAlignment="Top" Width="311" />
<TextBox Height="27" HorizontalAlignment="Left" Margin="138,55,0,0"
Name="textBoxOperand2" VerticalAlignment="Top" Width="311" />
<TextBox Height="27" HorizontalAlignment="Left" Margin="138,143,0,0"
Name="textBoxResult" VerticalAlignment="Top" Width="311" />
<Button Content="Sum" Height="28" HorizontalAlignment="Left" Margin="139,88,0,0"
Name="button1" VerticalAlignment="Top" Width="143" Click="button1_Click" />
<Label Content="Operand 1" Height="27" HorizontalAlignment="Left" Margin="12,22,0,0"
Name="label1" VerticalAlignment="Top" Width="120" />
<Label Content="Operand 2" Height="27" HorizontalAlignment="Left" Margin="12,55,0,0"
Name="label2" VerticalAlignment="Top" Width="120" />
<Label Content="Result" Height="27" HorizontalAlignment="Left" Margin="12,143,0,0"
Name="label3" VerticalAlignment="Top" Width="120" />
</Grid>
</Window>


The code behind is as follows:

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}

private decimal ProcessOperands(decimal operand1, decimal operand2)
{
decimal sum;
sum = operand1 + operand2;

return sum;
}

private void button1_Click(object sender, RoutedEventArgs e)
{
decimal operand1 = Decimal.Parse(this.textBoxOperand1.Text);
decimal operand2 = Decimal.Parse(this.textBoxOperand2.Text);

this.textBoxResult.Text = ProcessOperands(operand1, operand2).ToString();
}
}

Lets run the application now. Everything is working great. We enter numeric digits in the two operands fields. When we click Enter, the result appears in the Result text box. Now let us change the method call (ProcessOperands) to be an asynchronous call using Observable.ToAsync. We need to update the button’s click handler as follows:

private void button1_Click(object sender, RoutedEventArgs e)
{
decimal operand1 = Decimal.Parse(this.textBoxOperand1.Text);
decimal operand2 = Decimal.Parse(this.textBoxOperand2.Text);

Observable.ToAsync<decimal, decimal, decimal>(ProcessOperands)(operand1, operand2)
.Subscribe(
(result) => { this.textBoxResult.Text = result.ToString(); }
);
}

The code clearly shows that we have used an overload of ToAsync which takes two decimal values as arguments and returns a decimal value. We have used this as our ProcessOperand method is defined like that. You can see that we have used the value provided in the onNext parameter to populate the textBoxResult. Basically onNext is placed when the async code is finished execution and result is available. If we compare it to the code we have written for Asynchronous delegates, we realize that Rx has internally executed code for BeginInvoke and also called EndInvoke for us getting the result using IAsyncResult. If we look at the marble diagram, it should be like this.



In the marble diagram, this has shown to be placing an OnCompleted message afterwards. Let us verify that this event is generated. In the following code, we are updating the Background color to green when OnCompleted message is received from the Observable generated for the method.

private void button1_Click(object sender, RoutedEventArgs e)
{
decimal operand1 = Decimal.Parse(this.textBoxOperand1.Text);
decimal operand2 = Decimal.Parse(this.textBoxOperand2.Text);

Observable.ToAsync<decimal, decimal, decimal>(ProcessOperands)(operand1, operand2)
.Subscribe(
(result) => { this.textBoxResult.Text = result.ToString(); },
() => this.Background = Brushes.Green
);
}

Now we run the application and enter values in the operands text boxes. When we click the button, the textBoxResult is updated with the sum of two operands. The window also turns green. This is due to the code we have written in OnCompleted handler.



Long running methods and Rx Thread Management for generating asynchronous block:
Now you might be thinking that this is a very simple example. What if the method is a long running method taking a few seconds. Would it still be the same code. Let’s mimic that this method is taking a few seconds by putting Thread.Sleep in method code as follows:

private decimal ProcessOperands(decimal operand1, decimal operand2)
{
decimal sum;
sum = operand1 + operand2;

Thread.Sleep(5000);
}

If you run this and enter data in the input text boxes and click Sum. You get the following exception:



Why is this exception generated by just delaying in the asynchronous method? Basically we have caused the subscription to be on a ThreadPool thread. Since we are delaying for 5 seconds, all Rx messages (OnNext, OnCompleted and OnError) seem to be dispatched on the calling thread of subscriber.

It seems if there is a delay of more than 3 milliseconds then the OnNext messages are dispatched on a ThreadPool thread otherwise they are dispatched on the thread of the subscriber. In this case it is UI thread. If the delay is 3 milliseconds or lesser these messages are always dispatched on UI thread. This is true even though we know that ToAsync is causing the method to be executed on a ThreadPool thread.

Fig: When OnNext is received in more than 3 milliseconds:



Fig: When OnNext is received in 3 milliseconds or less:



How exceptions are handled?

As we have discussed [http://shujaatsiddiqi.blogspot.com/2010/12/asynchronous-delegate-exception-model.html] the runtime is silent about exceptions for Async delegates if we don’t call EndInvoke. It is not the case with Observable.ToAsync. It always generate exception message OnError when there is an exception in the method executed asynchronously. Let us change the code of ProcessOperands so that it throws an exception.

[DebuggerStepThrough]
private decimal ProcessOperands(decimal operand1, decimal operand2)
{
decimal sum;
sum = operand1 + operand2;

if (sum < 0)
{
throw new System.Exception("Exception in processing data!");
}

return sum;
}

The above code is resulting an exception if the sum of these two operands is negative. We also need to update the code so that IObservable generated from Observable.ToAsync has a non-default OnError handler. I have decorated the method with DebuggerStepThrough attribute so that Debugger doesn’t bother me as I have FCEs turned on. Let’s update button1_Click as follows:

private void button1_Click(object sender, RoutedEventArgs e)
{
decimal operand1 = Decimal.Parse(this.textBoxOperand1.Text);
decimal operand2 = Decimal.Parse(this.textBoxOperand2.Text);

Observable.ToAsync<decimal, decimal, decimal>(ProcessOperands)(operand1, operand2)
.Subscribe(
(result) => { this.textBoxResult.Text = result.ToString(); },
(ex) => this.Background = Brushes.Red,
() => this.Background = Brushes.Green
);
}

It just changes the background of the window to Red if there is an OnError message from the method. Let’s run the application and enter data 2 and -5 in the operand fields. As we know that their sum is -3, the background of the window should turn Red.


We can show this in marble diagram as follows:



Observing on Non-UI thread using different IScheduler:

Now we suppose that the method would always take more than 3 milliseconds. Can we still use ToAsync feature of Observable? Yes we can!

We just need to Observe on the Dispatcher. This can be done by using ObserveOn feature of IObservable. There are two methods provided for this purpose. One method allows us to generate the messages on any IScheduler (including built-in schedulers like Dispatcher, ThreadPool, TaskPool, Immediate, CurrentThread, NewThread). We can use any of the four overloads of this method. We can also directly use ObserveOnDispatcher method from IObservable. We have used the same as below.

private void button1_Click(object sender, RoutedEventArgs e)
{
decimal operand1 = Decimal.Parse(this.textBoxOperand1.Text);
decimal operand2 = Decimal.Parse(this.textBoxOperand2.Text);

Observable.ToAsync<decimal, decimal, decimal>(ProcessOperands)(operand1, operand2)
.ObserveOnDispatcher<decimal>()
.Subscribe(
(result) => { this.textBoxResult.Text = result.ToString(); },
(ex) => this.Background = Brushes.Red,
() => this.Background = Brushes.Green
);
}

Now we run the application. Although the method is being executed on a separate ThreadPool thread but the OnNext, OnError and OnCompleted messages are dispatched on UI thread.

Fig: Method executed on a ThreadPool thread


Fig: OnNext message generated on Main UI Thread


Fig: OnCompleted placed on Main UI thread


Fig: OnError placed on Main UI thread



Limitations:
Since this is a way to implement Anonymous asynchronous delegates using Reactive Extensions so it seems to have has the same limitation as anonymous asynchronous delegate (Func) has. We can not have out or ref parameters in the method that we want to execute asynchronously. In non-reactive model, we might easily implement named asynchronous delegate as a work around but in the reactive extension world there doesn't seem to be any alternative.

Download Code:

Wednesday, January 5, 2011

WPF - Messaging using Windows Pipes protocol

PipeStream was introduced in .net framework 3.5. It is a mechanism to support communication of messages between to processes. There are two types of pipes:

Anonymous Pipes:
Anonymous pipes can not be used over a network. Anonymous pipes are for one-way messaging. Anonymous pipes don't support message mode. They support inter-process communication mainly between a process and another process which is invoked by it. A reference of PipeStream object is passed to child process when invoking the child process.

Named Pipes
They support one-way and both-way (duplex) messaging. As their name implies, they use name of pipes for messaging. The name of the pipe should be system-wide unique. We will be using named pipes for our examples in this post.

As we discussed above, PipeStream is a mechanism for inter-process communication. These processes don't have to be on the same computer. NamedPipeClientStream has constructors to support servers on different computers. We just need to specify the Server name in those constructors and we should be good to go.


Namespace:
System.IO.Pipes


Named pipes can be used between processes on the same or other computers across the Windows network.

Communication between Client and Server:
Let's consider a scenario in which a server needs to send a single message to a client using PipeStream. They are in different processes and we are using Named version of Server and Client.

Before draining messages through the pipe, a server needs to have a connection established with a Client. If there is no request, it must wait for the connection. In the code below, a server is waiting for a connection using server's WaitForConnection. As soon as the connection is established, it writes through the pipe.

private void btnSendMessage_Click(object sender, RoutedEventArgs e)
{
using (var namedPipeStream =
new NamedPipeServerStream("namedPipeSynch", PipeDirection.InOut, 1, PipeTransmissionMode.Message))
{
namedPipeStream.WaitForConnection();

byte[] messageBytes = Encoding.UTF8.GetBytes(this.textBox1.Text);
namedPipeStream.Write(messageBytes, 0, messageBytes.Length);
}
}

The client needs to connect to the Server using Client's Connect method. This is a blocking call, it means that it has to wait until a connection is established. As soon as the connection is established, it can attempt to read as follows:

private void btnGetMessage_Click(object sender, RoutedEventArgs e)
{
using (var namedPipeClientStream = new NamedPipeClientStream(".", "namedPipeSynch", PipeDirection.InOut))
{
namedPipeClientStream.Connect();
namedPipeClientStream.ReadMode = PipeTransmissionMode.Message;
StreamReader streamReader = new StreamReader(namedPipeClientStream);
this.textBlockMessage.Text = streamReader.ReadToEnd();
}
}

Sending messages before a connection is established:
The communication must be established between client and server before writing message on the stream. If it is attempted to write a message before a connection is made, it results in InvalidOperationException. In the following image, a message is attempted to be pass through the pipe without calling WaitForConnection, resulting in the exception with appropriate error message.


Named Pipes between Two Clients:
Two NamedPipeClientStream can not communicate with each other.

Transmission Mode:
There are two available pipe transmission modes for PipeStream. They are as follows:
1. Byte
2. Message


It is a read-only property on the server. It can be specified in the constructor while instantiating the Server. For client, we can specify it after connecting it to the server before any transmission takes place.


Pipe Direction:
It is weird but I have noticed that for message mode transmission using PipeStream both Client and Server should be specified with PipeDirection as InOut. So if Server has PipeDirection as Out and Client is specified with In for direction, it would result in an UnauthorizedAccessException with familiar Access to the path is denied message.

Connecting a Non-Existing PipeStream Server:
We can specify name of the NamedPipeStreamServer to connect with it. It is possible that server is not available when we attempt to connect it. It must be remembered that this is a blocking call, the client would keep on waiting until the server becomes available. If you are attempting to connect on a UI thread then the UI thread keeps blocking. It is advisable to not make such calls on UI thread. It is also advisable to use an overload of Connect with some TimeOut value. If connection is unsuccessful, it results in a TimeOutException. We can also verify if the connection is successful using the IsConnected property of PipeStream. Since this is defined on PipeStream level, this is available for both Client and Server (Named and anonymous).

using (var namedPipeClientStream = new NamedPipeClientStream(".", "namedPipe", PipeDirection.InOut))
{
try
{
namedPipeClientStream.Connect(1000);

namedPipeClientStream.ReadMode = PipeTransmissionMode.Message;

StreamReader streamReader = new StreamReader(namedPipeClientStream);
this.textBlockMessage.Text = streamReader.ReadToEnd();
}
catch (TimeoutException ex)
{
MessageBox.Show(ex.Message);
}
}

In this example, Client would just blocks for 1 second for a server. If it is not able to connect to a server during that period, it would result in TimeOutException.

It must be remembered that there is no such overload available in the server which supports a TimeOut when waiting for connection.


Synchronous Vs ASynchronous Transmission:
PipeStream supports both Synchronous and Asynchronous transmission. This can be specified by using PipeOptions property of PipeStream.

The client and server can be individually set as synchronous / asynchronous i.e. it is possible that either of client / server is working in synch mode while the other is operating otherwise. The other most important thing is that PipeStream implements IDisposable. If you are using an Asynchronous operations like BeginWaitForConnection then as the object is disposed, it would execute the callback before even a connection is made. Now since the Server is already disposed, attempting to write something on the PipeStream or even just calling EndWaitForConnection would result in ObjectDisposedException. So we must be careful in using asynchronous operations for a PipeStream in specially using block as it would dispose the object when it finishes.


In order to do that, we would need to have a code like this:

private void btnSendAsynchMessage_Click(object sender, RoutedEventArgs e)
{
string MessageToSend = this.textBox1.Text;

if (!namedPipeStreamASynch.IsConnected)
{
namedPipeStreamASynch.BeginWaitForConnection(
(resultAsynch) =>
{
string MessageToSendLocal = MessageToSend;
try
{
namedPipeStreamASynch.EndWaitForConnection(resultAsynch);
WriteMessageToPipe(MessageToSendLocal);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}, null);
}
else
{
WriteMessageToPipe(MessageToSend);
}
}

The above code is basically the code of handler of click event of a button. It is using the Pipe Stream Server declared at the level of instance. If the server is not already connected, it would wait for the connection on a ThreadPool thread using BeginWaitForConnection method. As soon as it is connected, it would executed the lambda callback, ultimately resulting in pushing data to the pipe.

The above code was about waiting for the connection on a asynchronous fashion. We can also write on an asycnh way using BeginWrite functionality available with PipeStream. For achieving the same effect, look at this definition of WriteMessageToPipe method used in above code.

private void WriteMessageToPipe(string MessageToSend)
{
//Get bytes array of the message
byte[] messageBytes = Encoding.UTF8.GetBytes(MessageToSend);

//writing asynch way
namedPipeStreamASynch.BeginWrite(messageBytes, 0, messageBytes.Length,
(resultAsynchWrite) =>
{
try
{
//just to make sure there are no exceptions
namedPipeStreamASynch.EndWrite(resultAsynchWrite);
//namedPipeStreamASynch.Disconnect();
namedPipeStreamASynch.Flush();
//namedPipeStreamASynch.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}, null);
}

This would be invoking the Write operation on a separate ThreadPool thread. As the Write operation completes, the callback would execute. In the above code, we have just flushed the contents of the PipeStream. We can also close / disconnect the stream if this is the only communication required between the client and server.

It is great to learn that PipeStream's Read operation can also be asynchronous. It supports BeginRead / EndRead. Let's assume a PipeStream client invoking the asynchronous read operation.

private void btnASynchronousRead_Click(object sender, RoutedEventArgs e)
{
//if not already connected, get connected and set message mode
if (!namedPipeClientStream.IsConnected)
{
//still synchronous
namedPipeClientStream.Connect();

//Set message mode
namedPipeClientStream.ReadMode = PipeTransmissionMode.Message;
}

//setting any arbitrary size for message. It should be defined for the protocol and documented for developers.
byte[] buffer = new byte[1024];

//asynchronous read operation
namedPipeClientStream.BeginRead(buffer, 0, 1024,
(asynchResult) =>
{
try
{
//Just to make sure that there are no exceptions during Read operation
namedPipeClientStream.EndRead(asynchResult);

//Get the string from the message buffer
string message = Encoding.UTF8.GetString(buffer);

//Get rid of unnnecessary appending characters
message = message.Substring(0, message.IndexOf("\0"));

//Invoking the Dispatcher.Invoke as we are on ThreadPool thread
Dispatcher.BeginInvoke(
new Action(
() =>
{
//because of closure issues, copy the message to a local variable to the lambda expression
string messageLocal = message;

this.textBlockMessage.Text = messageLocal;
}), null);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message); //or any thing useful in case of exception
}
}, buffer); //pass the buffer as ASynchState supports Object type (TRICK)
}

Here the definition of PipeStreamClient used above as follows:
NamedPipeClientStream namedPipeClientStream = new NamedPipeClientStream(".", "namedPipe", PipeDirection.InOut);

It must have a Pipe Stream Server something like this:

NamedPipeServerStream namedPipeStreamASynch =
new NamedPipeServerStream("namedPipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous);

If we don't open the PipeStream server connection with Asynchronous mode then the execution of callback would result in exception.


I want to take a moment here to direct you to one of the post of the special exception model of Asynchronous delegates.

http://shujaatsiddiqi.blogspot.com/2010/12/asynchronous-delegate-exception-model.html

This code is still not purely asynchronous. Here Write operation on the PipeStream is still a blocking call. It can block the UI thread forever. Let's update the code to use asynchronous version of Write method (BeginWrite).

private void btnSendAsynchMessage_Click(object sender, RoutedEventArgs e)
{
string MessageToSend = this.textBox1.Text;

namedPipeStreamASynch.BeginWaitForConnection(
(resultAsynch) =>
{
try
{
string MessageToSendLocal = MessageToSend;

namedPipeStreamASynch.EndWaitForConnection(resultAsynch);
byte[] messageBytes = Encoding.UTF8.GetBytes(MessageToSendLocal);
//namedPipeStreamASynch.Write(messageBytes, 0, messageBytes.Length);
namedPipeStreamASynch.BeginWrite(messageBytes, 0, messageBytes.Length,
(resultAsynchWrite) =>
{
try
{
namedPipeStreamASynch.EndWrite(resultAsynchWrite);
namedPipeStreamASynch.Disconnect();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}, null);

}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}, null);
}

The above code would be using a ThreadPool thread to wait for the availability of a PipeStream Client for connection. As soon as a client becomes available, it creates another new ThreadPool thread for writing the contents of the TextBox to the pipe. May be you don't want to create so many threads for a simple write operation. In that case just create one ThreadPool thread for waiting for the connection. To write the contents to the Pipe, we can use the same thread.

Basically, writing the contents to pipe is not a feature of just server. It is rather defined in PipeStream class. This is inherited by all 4 client and server classes for PipeStream. We can introduce the similar use of Write (BeginWrite) for client.

Security of Transmission:
In order to apply security to a Pipe, we can create an instance of PipeSecurity and pass it to the SetAccessControl method of PipeStream. This would apply the access control entries in the PipeStream object to the pipe.

Data is an organization asset. The same data is shared across different processes using messages communicated through PipeStrream. If we want to make data secure, we need to apply access control entries to the PipeStream object. This would ensure the authorized use of the PipeStream.

Access to the Path is denied:
There might be many possible issues with setting up the connection between client(s) and server. It is annoying that most of the issues result in "Access to the Path is denied" message. I think had there been specialized messages for each issue it would have been a lot easier to trace the cause of the issue.


Download:

Saturday, December 11, 2010

WPF - ASynchronous Delegate Exception Model

In this post, we are going to discuss exception model of Asynchronous delegates. For those who have started development just starting with .net 4.0, they are old school for Task. Basically thread (including ThreadPool.QueueUserWorkItem based threads) are for providing "shoot and run" kind of flows. They don't us allow to return anything from them. If we needed to return a value, the only option we have is ASynchronous Delegate. It must be remembered that Asynchronous delegate would still be using ThreadPool thread so it will have all the benefits of using a ThreadPool thread.

Like BackgroundWorker, ASynchDelegate also has a special mechanism for dealing with exceptions raised during its operation. It is necessary to be aware of it. We will be discussing the use of ASynchDelegate in a sample WPF application. In this application, we will be taking input of two operands. The application would perform some complex calculation on these operands and display the result on the form. In order to keep the example simple, we would just sum these operands. We will not be verifying the inputs just for the same reason.


The XAML for the above display is as follows:

<Window x:Class="WpfApplication_ASynchDelegate.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WindowASynchDelegate" Height="389" Width="595">
<Grid>
<TextBox Height="27" HorizontalAlignment="Left" Margin="138,22,0,0"
Name="textBoxOperand1" VerticalAlignment="Top" Width="311" />
<TextBox Height="27" HorizontalAlignment="Left" Margin="138,55,0,0"
Name="textBoxOperand2" VerticalAlignment="Top" Width="311" />
<TextBox Height="27" HorizontalAlignment="Left" Margin="138,143,0,0"
Name="textBoxResult" VerticalAlignment="Top" Width="311" />
<Button Content="Sum" Height="28" HorizontalAlignment="Left" Margin="139,88,0,0"
Name="button1" VerticalAlignment="Top" Width="143" Click="button1_Click" />
<Label Content="Operand 1" Height="27" HorizontalAlignment="Left" Margin="12,22,0,0"
Name="label1" VerticalAlignment="Top" Width="120" />
<Label Content="Operand 2" Height="27" HorizontalAlignment="Left" Margin="12,55,0,0"
Name="label2" VerticalAlignment="Top" Width="120" />
<Label Content="Result" Height="27" HorizontalAlignment="Left" Margin="12,143,0,0"
Name="label3" VerticalAlignment="Top" Width="120" />
</Grid>
</Window>

The code behind of the above window is as follows:

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}

private decimal getSum(decimal operand1, decimal operand2)
{
decimal sum;
sum = operand1 + operand2;

return sum;
}

private void button1_Click(object sender, RoutedEventArgs e)
{
decimal operand1 = Decimal.Parse(this.textBoxOperand1.Text);
decimal operand2 = Decimal.Parse(this.textBoxOperand2.Text);

Func<decimal, decimal, decimal> getSumAsynchDelegate = getSum;

getSumAsynchDelegate.BeginInvoke(operand1, operand2,
(resultASynch) =>
{
var methodDelegate = (Func<decimal, decimal, decimal>)resultASynch.AsyncState;

this.Dispatcher.BeginInvoke(
new Action(() =>
this.textBoxResult.Text =
methodDelegate.EndInvoke(resultASynch).ToString()));
},
getSumAsynchDelegate);
}
}

In the Click event handler for the button, we have assigned the text entered in two input text boxes texBoxOperand1 and textBoxOperand2 to local variables operand1 and operand2. We have introduced an asynchronous delegate. This is expected to receive two decimal arguments and returns a decimal value. In the Asynchronous delegate declaration, the last value specified is the return type.

Func<decimal, decimal, decimal> getSumAsynchDelegate = getSum;

Although Asynchronous delegate seems to be similar to the Asynchronous methods (Asynchronous Programming Model - APM) because It has BeginInvoke and EndInvoke mechanism as in ASynchronous method and BeginInvoke returns IASynchResult as ASynchronous methods. But it must be remembered that BeginInvoke returns immediately after calling the method to the calling method. As discussed here, we can call BeginInvoke to invoke an Asynchronous delegate. It seems that we have provided four arguments to it. First two are for the method parameters [It depends on how many parameters you have for the method being called]. The third argument is the callback after the method finishes execution on a different thread. The last parameter is anything we want to pass. It is copied to ASynchState of the method. We can get this value in the callback. We have passed the delegate itself to ASynchState as we don't want to declare an instance member for it.

Now we discuss the lambda for the callback which gets called when asynchronous delegate finishes execution.

(resultASynch) =>
{
var methodDelegate = (Func<decimal, decimal, decimal>)resultASynch.AsyncState;

this.Dispatcher.BeginInvoke(
new Action(() =>
this.textBoxResult.Text =
methodDelegate.EndInvoke(resultASynch).ToString()));
},

As you can see, we have obtained the delegate from ASynchState property of resultASynch(IASynchResult). The interesting thing to notice is that we have used Dispatcher to copy value to textBoxResult.Text. This is because, unlike BackgroundWorker, the callback is not executed on UI thread. In order to get the returned value from the delegate, we need to call EndInvoke on the delegate passing IASynchResult as the argument. Since the method is expected to return a decimal value, we are converting it to string before assigning to the Text property of the text box.

Even if we don't call EndInvoke on ASynchronous Delegate, it still would finish execution. It wouldn't be making sense to use this delegate though in this kind of situation, as we are not expecting any returned value. But if we don't call EndInvoke then we lose any exception caused in the method called using asynchronous delegate. It is a silent exception. This is the same thing as we discussed in BackgroundWorker. We must be aware of all these silent failures in our application as it can lead our application to be in an unexpected state.

Let's update the method as follows:

[DebuggerNonUserCode]
private decimal getSum(decimal operand1, decimal operand2)
{
decimal sum;
sum = operand1 + operand2;

if (sum > 0)
throw new Exception("What did u do!");

return sum;
}

So if we don't call EndInvoke and update the definition of the method and don't call EndInvoke, the application would never know about the exception. If we don't use try / catch block with EndInvoke and the method results in an exception, the exception could end up in DispatcherUnhandledException if we are calling EndInvoke on a UIThread. Or AppDomain.CurrentDomain.UnhandledException if we are calling it in any other thread (as in the callback of asynchronous delegate).