web-dev-qa-db-fra.com

Comment faire en sorte qu'une méthode asynchrone retourne une valeur?

Je sais comment faire des méthodes Async mais disons que j'ai une méthode qui fait beaucoup de travail puis renvoie une valeur booléenne?

Comment renvoyer la valeur booléenne sur le rappel?

Clarification:

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

Je veux être capable de rendre cela asynchrone.

67
Overload119

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

void RunFooAsync(..., Action<bool> callback) {
     // do some stuff
     bool result = ...

     if(callback != null) callback(result);
}

Une autre approche consiste à déclencher 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<bool> outerTask = ...;
outerTask.ContinueWith(task =>
{
    bool result = task.Result;
    // do something with that
});
54
Marc Gravell

A partir de C # 5. , vous pouvez spécifier la méthode comme suit:

public async Task<bool> doAsyncOperation()
{
    // do work
    return true;
}

bool result = await doAsyncOperation();
116
Dave Arkell

La manière la plus simple de le faire est probablement de créer un délégué puis BeginInvoke, suivi d’une attente à l’avenir, et d’un EndInvoke.

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

public SomeMethod()
{
    var fooCaller = new Func<bool>(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);
}
4
Jim Mischel

Utilisez un BackgroundWorker. Il vous permettra d’obtenir des rappels à la fin et de suivre vos progrès. Vous pouvez définir la valeur Result sur les arguments de l'événement avec 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;
    }
3
NerdFury

Peut-être que vous pouvez essayer de commencer en invitant un délégué pointant sur votre méthode comme ceci:



    delegate string SynchOperation(string value);

    class Program
    {
        static void Main(string[] args)
        {
            BeginTheSynchronousOperation(CallbackOperation, "my value");
            Console.ReadLine();
        }

        static void BeginTheSynchronousOperation(AsyncCallback callback, string value)
        {
            SynchOperation op = new SynchOperation(SynchronousOperation);
            op.BeginInvoke(value, callback, op);
        }

        static string SynchronousOperation(string 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.

1
Omer Ben