Pergunta

Conceitualmente, gostaria de realizar o seguinte, mas tive problemas para entender como codificá-lo corretamente em C#:


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

Então, quando WorkerMethod() estiver concluído, execute isto:


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

Alguém pode dar um exemplo disso?

Foi útil?

Solução

O Trabalhador de fundo class foi adicionada ao .NET 2.0 exatamente para esse propósito.

Em poucas palavras você faz:

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

Você também pode adicionar coisas sofisticadas, como cancelamento e relatórios de progresso, se desejar :)

Outras dicas

No .Net 2, o BackgroundWorker foi introduzido, o que torna a execução de operações assíncronas muito 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();

No .Net 1 você tem que usar threads.

Você tem que usar AsyncCallBacks.Você pode usar AsyncCallBacks para especificar um delegado para um método e, em seguida, especificar métodos de retorno de chamada que serão chamados assim que a execução do método de destino for concluída.

Aqui está um pequeno exemplo, corra e veja você mesmo.

programa de classe {

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

    }
}

Embora existam várias possibilidades aqui, eu usaria um delegado, chamado de forma assíncrona usando BeginInvoke método.

Aviso :não esqueça de ligar sempre EndInvoke no IAsyncResult para evitar eventuais vazamentos de memória, conforme descrito em Este artigo.

Confira BackgroundWorker.

Use delegados assí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, não tenho certeza de como você deseja fazer isso.Pelo seu exemplo, parece que WorkerMethod não cria seu próprio thread para executar, mas você deseja chamar esse método em outro thread.

Nesse caso, crie um método de trabalho curto que chame WorkerMethod, em seguida, chame SomeOtherMethod e coloque esse método na fila em outro thread.Então, quando WorkerMethod for concluído, SomeOtherMethod será chamado.Por exemplo:

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top