Domanda

Concettualmente, vorrei realizzare quanto segue, ma ho avuto difficoltà a capire come codificarlo correttamente in C#:


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

Quindi, una volta completato WorkerMethod(), esegui questo:


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

Qualcuno può darci un esempio?

È stato utile?

Soluzione

IL BackgroundWorker è stata aggiunta a .NET 2.0 proprio per questo scopo.

In poche parole fai:

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

Puoi anche aggiungere cose fantasiose come cancellazioni e rapporti sui progressi, se lo desideri :)

Altri suggerimenti

In .Net 2 è stato introdotto BackgroundWorker, questo rende davvero semplice l'esecuzione di operazioni asincrone:

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

In .Net 1 devi usare i thread.

Devi usare AsyncCallBacks.È possibile utilizzare AsyncCallBacks per specificare un delegato a un metodo e quindi specificare metodi CallBack che vengono chiamati una volta completata l'esecuzione del metodo di destinazione.

Ecco un piccolo esempio, corri e guardalo tu stesso.

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

    }
}

Sebbene in questo caso siano disponibili diverse possibilità, utilizzerei un delegato, chiamato in modo asincrono using BeginInvoke metodo.

Avvertimento :non dimenticare di chiamare sempre EndInvoke sul IAsyncResult per evitare eventuali perdite di memoria, come descritto in Questo articolo.

Dai un'occhiata a BackgroundWorker.

Utilizza delegati asincroni:

// 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, non sono sicuro di come vuoi procedere.Dal tuo esempio, sembra che WorkerMethod non crei un proprio thread da eseguire, ma tu voglia chiamare quel metodo su un altro thread.

In tal caso, crea un metodo di lavoro breve che chiama WorkerMethod, quindi chiama SomeOtherMethod e accoda quel metodo su un altro thread.Quindi, al completamento di WorkerMethod, viene chiamato SomeOtherMethod.Per esempio:

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.
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top