Pregunta

Conceptualmente, me gustaría lograr lo siguiente pero he tenido problemas para entender cómo codificarlo correctamente en C#:


SomeMethod { // Member of AClass{}
    DoSomething;
    Start WorkerMethod() from BClass in another thread;
    DoSomethingElse;
}

Luego, cuando WorkerMethod() esté completo, ejecuta esto:


void SomeOtherMethod()  // Also member of AClass{}
{ ... }

¿Alguien puede dar un ejemplo de eso?

¿Fue útil?

Solución

El FondoTrabajador La clase se agregó a .NET 2.0 para este propósito exacto.

En pocas palabras lo que haces:

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += delegate { myBClass.DoHardWork(); }
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(SomeOtherMethod);
worker.RunWorkerAsync();

También puedes agregar cosas interesantes como cancelaciones e informes de progreso si lo deseas :)

Otros consejos

En .Net 2 se introdujo BackgroundWorker, lo que hace que ejecutar operaciones asíncronas sea realmente fácil:

BackgroundWorker bw = new BackgroundWorker { WorkerReportsProgress = true };

bw.DoWork += (sender, e) => 
   {
       //what happens here must not touch the form
       //as it's in a different thread
   };

bw.ProgressChanged += ( sender, e ) =>
   {
       //update progress bars here
   };

bw.RunWorkerCompleted += (sender, e) => 
   {
       //now you're back in the UI thread you can update the form
       //remember to dispose of bw now
   };

worker.RunWorkerAsync();

En .Net 1 tienes que usar hilos.

Tienes que usar AsyncCallBacks.Puede usar AsyncCallBacks para especificar un delegado a un método y luego especificar métodos de devolución de llamada que se llaman una vez que se completa la ejecución del método de destino.

Aquí tienes un pequeño ejemplo, corre y compruébalo tú mismo.

programa de clase {

    public delegate void AsyncMethodCaller();


    public static void WorkerMethod()
    {
        Console.WriteLine("I am the first method that is called.");
        Thread.Sleep(5000);
        Console.WriteLine("Exiting from WorkerMethod.");
    }

    public static void SomeOtherMethod(IAsyncResult result)
    {
        Console.WriteLine("I am called after the Worker Method completes.");
    }



    static void Main(string[] args)
    {
        AsyncMethodCaller asyncCaller = new AsyncMethodCaller(WorkerMethod);
        AsyncCallback callBack = new AsyncCallback(SomeOtherMethod);
        IAsyncResult result = asyncCaller.BeginInvoke(callBack, null);
        Console.WriteLine("Worker method has been called.");
        Console.WriteLine("Waiting for all invocations to complete.");
        Console.Read();

    }
}

Aunque hay varias posibilidades aquí, yo usaría un delegado, llamado asincrónicamente usando BeginInvoke método.

Advertencia :no olvides llamar siempre EndInvoke sobre el IAsyncResult para evitar posibles pérdidas de memoria, como se describe en Este artículo.

Consulte BackgroundWorker.

Utilice delegados asíncronos:

// Method that does the real work
public int SomeMethod(int someInput)
{
Thread.Sleep(20);
Console.WriteLine(”Processed input : {0}”,someInput);
return someInput+1;
} 


// Method that will be called after work is complete
public void EndSomeOtherMethod(IAsyncResult result)
{
SomeMethodDelegate myDelegate = result.AsyncState as SomeMethodDelegate;
// obtain the result
int resultVal = myDelegate.EndInvoke(result);
Console.WriteLine(”Returned output : {0}”,resultVal);
}

// Define a delegate
delegate int SomeMethodDelegate(int someInput);
SomeMethodDelegate someMethodDelegate = SomeMethod;

// Call the method that does the real work
// Give the method name that must be called once the work is completed.
someMethodDelegate.BeginInvoke(10, // Input parameter to SomeMethod()
EndSomeOtherMethod, // Callback Method
someMethodDelegate); // AsyncState

Ok, no estoy seguro de cómo quieres hacer esto.Según su ejemplo, parece que WorkerMethod no crea su propio subproceso para ejecutarlo, pero desea llamar a ese método en otro subproceso.

En ese caso, cree un método de trabajo corto que llame a WorkerMethod, luego llame a SomeOtherMethod y ponga ese método en cola en otro subproceso.Luego, cuando se completa WorkerMethod, se llama a SomeOtherMethod.Por ejemplo:

public class AClass
{
    public void SomeMethod()
    {
        DoSomething();

        ThreadPool.QueueUserWorkItem(delegate(object state)
        {
            BClass.WorkerMethod();
            SomeOtherMethod();
        });

        DoSomethingElse();
    }

    private void SomeOtherMethod()
    {
        // handle the fact that WorkerMethod has completed. 
        // Note that this is called on the Worker Thread, not
        // the main thread.
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top