Click here to Skip to main content
13,349,539 members (52,427 online)
Click here to Skip to main content
Add your own
alternative version

Stats

29.1K views
330 downloads
27 bookmarked
Posted 9 Aug 2010

How to Manage Multiple Asynchronous Calls by using Delegates

, 9 Aug 2010
Rate this:
Please Sign up or sign in to vote.
How to Manage Multiple Asynchronous Calls by using Delegates

Introduction

There are tons of ways on making asynchronous calls in .NET, and you should choose which one to use based on different scenarios. The scenario I want to cover here is how to deal with a situation where you need to make multiple asynchronous calls, and wait until all of them are completed in order to move on to the next step.

This is a typical situation in which you need to make multiple database calls, and wait for all the result sets to come back before continuing your process.

The Problem

In this example, you have a method SomeRandomNumber, which takes some time to execute, and will return an integer value. You will have to make 3 asynchronous calls to this method and wait until all of them are completed.

private static int SomeRandomNumber(int waitTime)
{
    Thread.Sleep(waitTime);
    return rnd.Next();
}

One of the most common solutions is to put all asynchronous calls to the ThreadPool, and you will need a loop to check if they are all completed, based on some global bool flag in your instance. First of all, the code is not clean, and this imperative style is hard to control in multiple threading situation. You can't be sure no one else will change your flag!

private int? threadOneResult;
private int? threadTwoResult;
private int? threadThreeResult;

public void AsyncCallsWithThreadPool()
{
    ThreadPool.QueueUserWorkItem(ThreadOne, 1000);
    ThreadPool.QueueUserWorkItem(ThreadTwo, 5000);
    ThreadPool.QueueUserWorkItem(ThreadThree, 10000);

    while (threadOneResult == null ||
        threadTwoResult == null ||
        threadThreeResult == null)
    {
        Thread.Sleep(100);
    }

    // continue
    Console.WriteLine(
        String.Format("Result: {0}\t{1}\t{2}",
        threadOneResult,
        threadTwoResult,
        threadThreeResult));
}

ThreadOne, ThreadTwo, and ThreadThree put back the result to the global int? variables. After all three threads are completed, the above method will get out of the while loop.

private void ThreadOne(object state)
{
    threadOneResult = SomeRandomNumber((int)state);
}

private void ThreadTwo(object state)
{
    threadTwoResult = SomeRandomNumber((int)state);
}

private void ThreadThree(object state)
{
    threadThreeResult = SomeRandomNumber((int)state);
}

The Solution

The methods BeginInvoke and EndInvoke will do all the work for you. BeginInvoke will process your asynchronous call in a new thread. EndInvoke will return the result from that thread. If the thread is not completed when you are calling EndInvoke, it will wait. You don't have to implement your wait loop in the main thread. The status of each asynchronous operation is saved in the IAsyncResult object, so one delegate can handle multiple invokes.

This approach can eliminate all the unnecessary global variables, so your asynchronous logic does not need to rely on the state in this instance. This looks clean. The most important thing is that this keeps your threading structure simple.

public void AsyncCallsInDelegate()
{
    GetNumber deleg = new GetNumber(SomeRandomNumber);

    IAsyncResult rst1 = deleg.BeginInvoke(1000, null, null);
    IAsyncResult rst2 = deleg.BeginInvoke(5000, null, null);
    IAsyncResult rst3 = deleg.BeginInvoke(10000, null, null);

    Console.WriteLine(
        String.Format("Result: {0}\t{1}\t{2}",
        deleg.EndInvoke(rst1),
        deleg.EndInvoke(rst2),
        deleg.EndInvoke(rst3)));
}

Life is getting better in .NET 3.5. You can use the generic delegate Func<int> to save the work of declaring a new delegate:

public void AsyncCallsInGenericDelege()
{
    Func<int> deleg = new Func<int>(SomeRandomNumber);

    IAsyncResult rst1 = deleg.BeginInvoke(1000, null, null);
    IAsyncResult rst2 = deleg.BeginInvoke(5000, null, null);
    IAsyncResult rst3 = deleg.BeginInvoke(10000, null, null);

    Console.WriteLine(
        String.Format("Result: {0}\t{1}\t{2}",
        deleg.EndInvoke(rst1),
        deleg.EndInvoke(rst2),
        deleg.EndInvoke(rst3)));
}

History

  • 8/8/2010 - First release on CodeProject

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

JasonChing
Software Developer Fidelity
Hong Kong Hong Kong
No Biography provided

You may also be interested in...

Pro
Pro

Comments and Discussions

 
Questionrofl i seen bull crap but who ever wrote this worthless peice of crap is one dumb sob Pin
Member 121615723-Dec-15 14:05
memberMember 121615723-Dec-15 14:05 
GeneralSometimes the simplest... Pin
Member 142630218-Aug-10 11:40
memberMember 142630218-Aug-10 11:40 
GeneralMy Vote of 4... Well it Helped Me Pin
all4gsus17-Aug-10 4:55
memberall4gsus17-Aug-10 4:55 
GeneralMy vote of 1 Pin
Mark Nischalke17-Aug-10 3:22
mvpMark Nischalke17-Aug-10 3:22 
General[My vote of 1] Nothing new Pin
Mark Nischalke8-Aug-10 8:31
mvpMark Nischalke8-Aug-10 8:31 
GeneralRe: [My vote of 1] Nothing new Pin
StNickolay10-Aug-10 6:41
memberStNickolay10-Aug-10 6:41 
GeneralRe: [My vote of 1] Nothing new Pin
Mark Nischalke10-Aug-10 7:08
mvpMark Nischalke10-Aug-10 7:08 
GeneralRe: [My vote of 1] Nothing new Pin
DaProgramma16-Aug-10 21:34
memberDaProgramma16-Aug-10 21:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.180111.1 | Last Updated 9 Aug 2010
Article Copyright 2010 by JasonChing
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid