How to make an Asynchronous Method return a value?

C#Asynchronous

C# Problem Overview


I know how to make Async methods but say I have a method that does a lot of work then returns a boolean value?

How do I return the boolean value on the callback?

Clarification:

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

I want to be able to make this asynchronous.

C# Solutions


Solution 1 - C#

From C# 5.0, you can specify the method as

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

bool result = await doAsyncOperation();

Solution 2 - C#

There are a few ways of doing that... the simplest is to have the async method also do the follow-on operation. Another popular approach is to pass in a callback, i.e.

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

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

Another approach would be to raise an event (with the result in the event-args data) when the async operation is complete.

Also, if you are using the TPL, you can use ContinueWith:

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

Solution 3 - C#

Probably the simplest way to do it is to create a delegate and then BeginInvoke, followed by a wait at some time in the future, and an 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);
}

Solution 4 - C#

Use a BackgroundWorker. It will allow you to get callbacks on completion and allow you to track progress. You can set the Result value on the event arguments to the resulting value.

    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;
    }

Solution 5 - C#

Perhaps you can try to BeginInvoke a delegate pointing to your method like so:



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





Then use the value in the method you sent as AsyncCallback to continue..

Solution 6 - C#

You should use the EndXXX of your async method to return the value. EndXXX should wait until there is a result using the IAsyncResult's WaitHandle and than return with the value.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionOverload119View Question on Stackoverflow
Solution 1 - C#Dave ArkellView Answer on Stackoverflow
Solution 2 - C#Marc GravellView Answer on Stackoverflow
Solution 3 - C#Jim MischelView Answer on Stackoverflow
Solution 4 - C#NerdFuryView Answer on Stackoverflow
Solution 5 - C#Omer BenView Answer on Stackoverflow
Solution 6 - C#the_drowView Answer on Stackoverflow