Sandbox
Sandbox

Reputation: 8178

How to make a series of asynchronous calls and then use the value returned by first thread?

I want to make asynchronous calls and then process the value returned by first thread. I don't want to use Parallel library. I can just use .Net 2.0. I have written the following program which should suffice my requirements. But can someone please point out if there is a better solution? Thanks.

Here is my code:

class Program
{
    private static Worker _worker2;
    private static Worker _worker3;
    private static Worker _worker4;
    private static Worker _worker1;
    delegate void DoWorkDelegate(object param);

    private static Worker _firstReturnedWorker = null;
    private static object lockObject = new object();

    public static void Main()
    {
        _worker1 = new Worker();
        _worker2 = new Worker();
        _worker3 = new Worker();
        _worker4 = new Worker();

        int i = 10;
        DoWorkDelegate d1 = new DoWorkDelegate(_worker1.OnDoWork);
        d1.BeginInvoke(1, OnThreadReturned, ++i);

        DoWorkDelegate d2 = new DoWorkDelegate(_worker2.OnDoWork);
        d2.BeginInvoke(2, OnThreadReturned, ++i);

        DoWorkDelegate d3 = new DoWorkDelegate(_worker3.OnDoWork);
        d3.BeginInvoke(3, OnThreadReturned, ++i);

        DoWorkDelegate d4 = new DoWorkDelegate(_worker4.OnDoWork);
        d4.BeginInvoke(4, OnThreadReturned, ++i);

        Console.ReadKey();
    }
    private static void OnThreadReturned(IAsyncResult ar)
    {
        lock (lockObject)
        {
            if (_firstReturnedWorker == null)
            {                    
                var workerIdentifier = (int)ar.AsyncState;
                switch (workerIdentifier)
                {
                    case 11:
                        _firstReturnedWorker = _worker1;
                        break;
                    case 12:
                        _firstReturnedWorker = _worker2;
                        break;
                    case 13:
                        _firstReturnedWorker = _worker3;
                        break;
                    case 14:
                        _firstReturnedWorker = _worker4;
                        break;
                }
            }
            else
            {
                return;
            }
        }
        Console.WriteLine("First result received was {0}", _firstReturnedWorker.ReturnedValue);
    }
}

public class Worker
{
    public string ReturnedValue { get; private set; }

    public void OnDoWork(object value)
    {
        ReturnedValue = Process((int)value);
    }

    private string Process(int numberToProcess)
    {
        return string.Format("{0} was processed by {1}", numberToProcess, Thread.CurrentThread.ManagedThreadId);
    }
}

Upvotes: 2

Views: 148

Answers (1)

Nick Butler
Nick Butler

Reputation: 24413

Your code looks like it should work, so ok so far.

You could clean it up a bit by passing the Worker instance objects as the AsyncState instead of the magic number. Then you wouldn't need the switch in OnThreadReturned either.


The alternative would be to put all the IAsyncResult.AsyncWaitHandle's in an array and call WaitHandle.WaitAny. This is more overhead though, as the WaitHandle's are created on demand, so won't be needed in your callback solution. They are actual kernel objects, so this can matter.

Upvotes: 1

Related Questions