Improve Your Technology

Just another blog for techology

Invoking Methods Asynchronously using Delegates

Invoking Methods Asynchronously using Delegates

Introduction

Asynchronous operation improves the program responsiveness and availability. In my past article titled Asynchronous Programming In .NET , I explained how to design your components with built-in support for asynchronous operations. But what if some one has already developed the component and that too without asynchronous programming support? In such cases delegates can come to the rescue. In fact that is the topic of this article.

Delegates and asynchronous operations

Delegates provide a built-in way to call a method asynchronously. Whenever you create an instance of the delegate, it automatically provides you with two methods.

  • BeginInvoke(parameter list, AsyncCallback callback, object state)
  • EndInvoke(IAsyncResult result)

Using the BeginInvoke method you call the method under consideration. When the method finishes, .NET calls the supplied callback function inside which you are  supposed to call the EndInvoke method. Behind the scene these methods use threads  from the .NET ThreadPool.

BeginInvoke method

The BeginInvoke method accepts all the parameters as per the method signature. For example, if your delegate signature is:

public delegate int AddNumbersDelegate(int x,int y);

then BeginInvoke will accept x and y as first two parameters.

Next comes the AsyncCallback instance. This is another delegate that points to the callback function that will be called when the method completes. The callback function mentioned above must have following signature:

public void MyCallback(IAsyncResult result)

Finally, you can pass some state information to the method via state parameter. This is useful in case you want to pass some information other than method parameters.

EndInvoke method

The EndInvoke method takes only one parameter that is of type IAsyncResult. At runtime this parameter provides information about the state information being passed, delegate that is invoking the method etc. Also, the EndInvoke method gives you the return value of the method being invoked.

Example

Let’s see how it works with an example. The example consists of three classes – Class1, Class2 and Class3. Class1 is the class that contains Main() and is used to actually invoke the method in asynchronous manner. Class2 is the class that contains a method (Add()) that we want to call asynchronously. Class3 contains a method (MyCallback()) that will be supplied as a callback to the BeginInvoke() method.

using System;

using System.Runtime.Remoting.Messaging;

namespace AsyncViaDelegates

{

public delegate int AddNumbersDelegate(int x,int y);

class Class1

{

[STAThread]

static void Main(string[] args)

{

                Class2 c2=new Class2();

                Class3 c3=new Class3();

                AsyncCallback callback=new AsyncCallback(c3.MyCallback);

                int state=100;

                AddNumbersDelegate d=new AddNumbersDelegate(c2.Add);

                d.BeginInvoke( 10,20,callback,state);

                System.Threading.Thread.Sleep(3000);

}

}

 

class Class2

{

                public int Add(int a,int b)

                {

                                return a+b;

                }

}

 

class Class3

{

                public void MyCallback(IAsyncResult result)

                {

                                AsyncResult ar=(AsyncResult)result;

                                AddNumbersDelegate d=

                                (AddNumbersDelegate)ar.AsyncDelegate;

                                int state=(int)ar.AsyncState;

                                int i=d.EndInvoke(result);

                                Console.WriteLine(i);

                                Console.WriteLine(state);

                                Console.ReadLine();

                }

}

}

  • We begin by importing two namespaces. The second one is important as it contains AsyncResult class used later in the code.
  • We declared a delegate called AddNumbersDelegate that accepts two integers and returns an integer
  • The class Class2 is the class that actually contains the function that we want to call asynchronously. In our example this function is Add()
  • Note that since we want to call this function via the delegate our delegate signature matches with the signature of Add.
  • The function simply accepts two integer parameters and returns sum of those parameters
  • We also have Class3 that contains the definition of the callback function (MyCallback)
  • In the Main() method we created the instances of Class2 and Class3
  • Then we created an instance of AsyncCallback delegate by passing reference to the MyCallback method. This instance will passed to the BeginInvoke() method later
  • We then declared an integer variable called state. This variable do not take part in any processing. We are using it just to illustrate how to pass the state information to the delegates
  • Next, we created the instance of AddNumbersDelegate delegate called d and pass the reference of Add() method to it.
  • Normally i.e. in synchronous mode you would have invoked this delegate as d(10,20) but here we want to invoke the Add() method asynchronously and hence we used the BeginInvoke() method of the delegate.
  • As explained earlier, the BeginInvoke method accepts all the parameters of the actual method (Add) followed by a callback function and state information.
  • We then halt the program execution for 3 seconds so that the callback function (MyCallback) will be called. In real life situation you can perform some other processing instead.
  • The callback function receives an instance of a class that implements IAsyncResult interface. .NET framework contains one such class called AsyncResult. In fact instance of this class is what you receive in the callback function.
  • The AsyncResult class contains a property called AsyncDelegate that gives the reference to the delegate on which you called BeginInvoke() method. It also provides the state information passed while calling BeginInvoke() through the AsyncState property.
  • Using the delegate reference mentioned above we called EndInvoke() method on the delegate. The return value of Add() is obtained via this call to EndInvoke() method.
  • Finally, we simply print the results on the console.

Summary

.NET provides native support for asynchronous operations. This article explained how to invoke methods asynchronously using delegates. This method is useful when the component developer has not provided asynchronous support for the component but you still want to call the methods asynchronously. The disadvantage of this method, however, is that you need to define your own delegate.

July 31, 2008 Posted by | Delegates | , | Leave a comment

Thread Synchronization

Using Monitor Class For Thread Synchronization

 

Introduction

 

While developing a multithreaded application it is very important to maintain synchronization between multiple calls to the same method. Consider for example that you have a function that writes to a file. If at the same time multiple threads call this function it is bound to throw an exception as previous method call is yet to finish with the file. To avoid such situations you can use Monitor class.

Namespaces Involved

 

Following namespaces are involved in our example:

  • System
  • System.Threading
  • System.IO
  • System.Text
  •  

Using Monitor class

 

Monitor class can synchronize method calls using its Enter and Exit methods. Following code shows how these methods work:

 

Monitor.Enter(Me)

Dim fs As FileStream = New FileStream

(“C:\Temp\SyncTest.txt”, FileMode.Append)

Dim t As Thread = Thread.CurrentThread

fs.Write(Encoding.ASCII.GetBytes(t.Name & vbCrLf),

0, t.Name.Length + 2)

Dim i As Integer

For i = 0 To 10000

   fs.Write(Encoding.ASCII.GetBytes(i & “,”),

   0, i.ToString().Length + 1)

Next

fs.Close()

Monitor.Exit(Me)

 

Here, we called Monitor.Enter method at the start of the method followed by our code that writes into a file. Once the writing operation is complete we call Monitor.Exit method. This ensures that till the time one thread is executing the function any other thread can not execute the same function. You can easily check what happens if you do not use Monitor class by simply commenting these two lines.

 

 

Using ThreadPool Class

 

Introduction

 

You can use Thread class directly to create and run a new thread. Even though creating threads in this fashion is easy there is still easier way to do that. ThreadPool class allows you to simply place a function in a queue which is executed by the ThreadPool. ThreadPool internally maintains a pool of threads that are used to execute your code as and when required. In fact ThreadPool operations are more efficient that using Thread class directly.

Namespaces Involved

 

Following namespaces are involved:

  • System
  • System.Threading

 

QueueUserWorkItem method

 

The QueueUserWorkItem method of ThreadPool class simply accepts an instance of type WaitCallback. The WaitCallback class in turn accepts an address of the function you want to execute. The QueueUserWorkItem method basically puts your function in queue and executes as and when a thread is available. Following example shows how this method is used:

 

Public Sub QueueUserWorkItemTest()

   Dim wc As New WaitCallback(AddressOf MyWaitCallback)

   ThreadPool.QueueUserWorkItem(wc)

End Sub

 

Public Sub MyWaitCallback(ByVal state As Object)

   Console.WriteLine(“MyWaitCallback called”)

End Sub

Here,

  1. We first created an instance of WaitCallBack delegate passing it the address of our function.
  2. We then call shared method – QueueUserWorkItem – of ThreadPool class that accepts this delegate as a parameter.
  3. The function that will be run over the thread simply outputs some text on the console.

 

RegisterWaitForSingleObject method

 

The RegisterWaitForSingleObject method of ThreadPool class accepts an instance WaitHandle class and WaitOrTimerCallback class. WaitHandle class is typically an instance of AutoResetEvent or ManualResetEvent. These classes basically signal to the ThreadPool that your function can now be called. WaitOrTimerCallback instance is nothing but a delegate for your function. Following code shows how this method is used:

 

Public Sub ShowDemoRegisterWaitForSingleObject()

   Dim wtc As New

   WaitOrTimerCallback(AddressOf MyWaitOrTimerCallback)

   Dim myevent As New AutoResetEvent(False)

   ThreadPool.RegisterWaitForSingleObject

   (myevent, wtc, Nothing, 20000, True)

   myevent.Set()

End Sub

 

Public Sub MyWaitOrTimerCallback

(ByVal state As Object, ByVal timeout As Boolean)

   Console.WriteLine(“MyWaitOrTimerCallback called”)

End Sub

Here,

  • We first create a WaitOtTimerCallBack delegate by passing it the address of our function.
  • Next, we create an instance of AutoResetEvent.
  • RegisterWaitForSingleObject method of ThreadPool class is then called.
  • Note that unless you call Set() method on the AutoResetEvent, your function will not be executed. Calling this method indicates to ThreadPool that the method can now be called on a thread from the pool.
  •  

I hope you must have found the article useful. In the next article, I will show you how to use System.Threading.Timer class to execute your function repeatedly after certain time interval.

 

 

Using Timer Class

 

Introduction

 

If you have programmed in VB6 before then probably you are familiar with Timer control. The Timer control triggers a code after certain interval of time. This control is typically used on windows forms. Similar control does exists for Windows Forms as well. What if you need such timer functionality on a thread of your classes (not on forms)? The System.Threading.Timer class can be used in such cases. This class automatically uses Thread Pool for executing your code.

Namespaces Involved

 

Following namespaces are involved:

  • System
  • System.Threading

 

Using System.Threading.Timer Class

 

In order to use Timer class you need to create an instance of it as shown below:

 

Public Sub StartTimer()

  Dim tcb As New TimerCallback(AddressOf Me.TimerMethod)

  Dim objTimer As Timer

  objTimer = New Timer(tcb, Nothing,

  TimeSpan.FromSeconds(5),

  TimeSpan.FromSeconds(10))

End Sub

 

Public Sub TimerMethod(ByVal state As Object)

   MsgBox(“The Timer invoked this method.”)

End Sub

 

Here, we created an instance of Timer class and passed a TimerCallBack and interval details to it. The third parameter represents the delay in milliseconds after which the method will be called for the first time. The forth parameter represents the interval in milliseconds that will be elapsed between the consecutive method calls. In our example the timer will start 5 seconds after creation of the instance. Then after 10 seconds it will fire again and again.

 

July 11, 2008 Posted by | Delegates | , | 1 Comment