¿Cómo hacer una serie de llamadas asincrónicas y luego usar el valor devuelto por el primer hilo?

Quiero hacer llamadas asincrónicas y luego procesar el valor devuelto por el primer hilo. No quiero usar la biblioteca paralela. Solo puedo usar .Net 2.0. He escrito el siguiente programa que debería ser suficiente para mis requisitos. Pero, ¿alguien puede señalar si hay una solución mejor? Gracias.

Aquí está mi código:

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);
    }
}

preguntado el 03 de mayo de 12 a las 13:05

1 Respuestas

Su código parece que debería funcionar, así que está bien hasta ahora.

Podría limpiarlo un poco pasando los objetos de instancia de Worker como el AsyncState en lugar del número mágico. Entonces no necesitarías el switch in OnThreadReturned ya sea.


La alternativa sería poner todos los IAsyncResult.AsyncWaitHandleestá en una matriz y llama WaitHandle.WaitAny. Sin embargo, esto es más general, ya que el WaitHandlese crean bajo demanda, por lo que no serán necesarios en su solución de devolución de llamada. Son objetos reales del núcleo, por lo que esto puede ser importante.

contestado el 03 de mayo de 12 a las 14:05

Usar WaitHandler.WaitAny me parece más elegante. Pero, una vez que consiga el mango. ¿Cómo identifico qué instancia de trabajador se debe usar? var arrOfHandles = new WaitHandle[] { ai1.AsyncWaitHandle, ai2.AsyncWaitHandle, ai3.AsyncWaitHandle, ai4.AsyncWaitHandle }; var index = WaitHandle.WaitAny(arrOfHandles); var identificador = arrOfHandles[índice]; - Salvadera

El índice devuelto de WaitHandle.WaitAny es el índice en la matriz de WaitHandles que pasas como parámetro. Así que si vuelve 0, tú lo sabes _worker1 completado primero. - nick mayordomo

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.