Comment faire pour qu’une méthode asynchrone retourne une valeur?

Je sais comment faire des méthodes asynchrones, mais disons que j’ai une méthode qui fait beaucoup de travail puis retourne une valeur booléenne?

Comment retourner la valeur booléenne sur le rappel?

Clarification :

public bool Foo(){ Thread.Sleep(100000); // Do work return true; } 

Je veux pouvoir rendre cela asynchrone.

Il y a plusieurs façons de le faire … le plus simple est de faire en sorte que la méthode asynchrone fasse également l’opération suivante. Une autre approche populaire consiste à passer un rappel, c’est-à-dire

 void RunFooAsync(..., Action callback) { // do some stuff bool result = ... if(callback != null) callback(result); } 

Une autre approche serait de générer un événement (avec le résultat dans les données event-args) lorsque l’opération asynchrone est terminée.

De plus, si vous utilisez la TPL, vous pouvez utiliser ContinueWith :

 Task outerTask = ...; outerTask.ContinueWith(task => { bool result = task.Result; // do something with that }); 

A partir de C # 5.0 , vous pouvez spécifier la méthode comme

 public async Task doAsyncOperation() { // do work return true; } bool result = await doAsyncOperation(); 

La façon la plus simple de le faire est probablement de créer un délégué, puis BeginInvoke , suivi d’une attente à un moment donné et d’un EndInvoke .

 public bool Foo(){ Thread.Sleep(100000); // Do work return true; } public SomeMethod() { var fooCaller = new Func(Foo); // Call the method asynchronously var asyncResult = fooCaller.BeginInvoke(null, null); // Potentially do other work while the asynchronous method is executing. // Finally, wait for result asyncResult.AsyncWaitHandle.WaitOne(); bool fooResult = fooCaller.EndInvoke(asyncResult); Console.WriteLine("Foo returned {0}", fooResult); } 

Utilisez un BackgroundWorker. Cela vous permettra d’obtenir des rappels à la fin et de suivre les progrès. Vous pouvez définir la valeur Result sur les arguments d’événement à la valeur résultante.

  public void UseBackgroundWorker() { var worker = new BackgroundWorker(); worker.DoWork += DoWork; worker.RunWorkerCompleted += WorkDone; worker.RunWorkerAsync("input"); } public void DoWork(object sender, DoWorkEventArgs e) { e.Result = e.Argument.Equals("input"); Thread.Sleep(1000); } public void WorkDone(object sender, RunWorkerCompletedEventArgs e) { var result = (bool) e.Result; } 

Peut-être que vous pouvez essayer de commencer Invoquer un délégué pointant vers votre méthode comme suit:

delegate ssortingng SynchOperation(ssortingng value); class Program { static void Main(ssortingng[] args) { BeginTheSynchronousOperation(CallbackOperation, "my value"); Console.ReadLine(); } static void BeginTheSynchronousOperation(AsyncCallback callback, ssortingng value) { SynchOperation op = new SynchOperation(SynchronousOperation); op.BeginInvoke(value, callback, op); } static ssortingng SynchronousOperation(ssortingng value) { Thread.Sleep(10000); return value; } static void CallbackOperation(IAsyncResult result) { // get your delegate var ar = result.AsyncState as SynchOperation; // end invoke and get value var returned = ar.EndInvoke(result); Console.WriteLine(returned); } }
delegate ssortingng SynchOperation(ssortingng value); class Program { static void Main(ssortingng[] args) { BeginTheSynchronousOperation(CallbackOperation, "my value"); Console.ReadLine(); } static void BeginTheSynchronousOperation(AsyncCallback callback, ssortingng value) { SynchOperation op = new SynchOperation(SynchronousOperation); op.BeginInvoke(value, callback, op); } static ssortingng SynchronousOperation(ssortingng value) { Thread.Sleep(10000); return value; } static void CallbackOperation(IAsyncResult result) { // get your delegate var ar = result.AsyncState as SynchOperation; // end invoke and get value var returned = ar.EndInvoke(result); Console.WriteLine(returned); } } 

Ensuite, utilisez la valeur de la méthode que vous avez envoyée en tant que AsyncCallback pour continuer.

Vous devez utiliser EndXXX de votre méthode async pour renvoyer la valeur. EndXXX devrait attendre qu’il y ait un résultat en utilisant le WaitHandle de l’IAsyncResult et renvoyer avec la valeur.