Tuesday, October 13, 2009

Design Patterns - Fire and Forget Pattern

Often in modeling for application development, you want a process to call another process and continue the process flow without waiting for a response from the called process. This pattern is called the "fire and forget" pattern.
This can be achieved in C# using the delegates.
Delegate has the following options which will help to achieve the fire and forget pattern.
Invoke (Synchronous)
BeginInvoke and EndInvoke (Asynchronous)
DynamicInvoke (Synchronous)

The difference between Invoke and DynamicInvoke is that, Invoke needs the instance of object to execute the method while DynamicInvoke doesn't need. We will be using BeginInvoke, EndInvoke and DynamicInvoke to achieve the "Fire and Forget" pattern.

public class ThreadUtils

{
delegate void DelegateWrapper(Delegate d, object[] args);
static DelegateWrapper wrapperInstance = new DelegateWrapper(InvokeWrappedDelegate);
static AsyncCallback callback = new AsyncCallback(EndWrapperInvoke);

public static void FireAndForget(Delegate d, params object[] args)
{
wrapperInstance.BeginInvoke(d, args, callback, null);
}

static void InvokeWrappedDelegate(Delegate d, object[] args)
{
d.DynamicInvoke(args);
}

static void EndWrapperInvoke(IAsyncResult ar)
{
wrapperInstance.EndInvoke(ar);
ar.AsyncWaitHandle.Close();
}


This "ThreadUtils" class is provided by Peter A Boomberg in his article on "Fire and Forget" pattern.

FireAndForget method takes delegate as input and invokes it's own delegate asynchronously and that delegate executes the one you have provided synchronosuly. At the same time, ThreadUtils class takes care of the dirty job of calling EndInvoke on the internal delegate using the AsynCallback mechanism.

Invoking code

class Program

{
delegate void InsertDelegate(string first, string second, int num);

static void Main(string[] args)
{
Delegate dWrite = new InsertDelegate(WriteIt);
for (int i = 0; i < 1000; i++)
{
ThreadUtils.FireAndForget(dWrite, new object[] { "hoohoo", "hahaa", i });
}
}
static void WriteIt(string first, string second, int num)
{
//do some intesive IO operations
}

No comments:

Post a Comment