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:

No comments: