Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I have to use await for a method to run asynchronously. What if I don't want to wait for the method to finish before continuing? [duplicate]

I've been pouring through MSDN docs all day, and their philosophy of asynchronous coding is confusing me. As I understand it, the thread that calls the async method will not be blocked if the async method is called. Yet, async is always paired in examples with await, which appears to negate the async-ness, making it so that the outer method DOES have to wait for the code to execute anyway. Shouldn't I be able to call an async method and then continue with the execution of the outer method?

This is the scenario I've been encountering, more or less:

void reportSomethingHappened(info)
    - Collect info
    - HTTP POST info to logging server (ie. mixpanel, sentry)

And here would be a calling method:

void largerProcess
    if (whatever)
        reportSomethingHappened();
    bla;
    bla;

As far as I understand, since POST requests can be done asynchronously, I should be able to make reportSomethingHappened() into an async method (by, AFAIK, await-ing the webrequest, and adding the async keyword).

But the largerProcess method doesn't need to wait for (ie. await) the reporting method to finish in order to execute bla bla. Yet, VS tells me that with an async method I can either await it, or it will happen synchronously, and block. Doesn't that defeat the purpose of doing it separately?

How do I write this so that reportSomethingHappened doesn't block execution of largerProcess? (Which is inherently confusing me, because I thought that was the point of async all along)

like image 697
thefistopher Avatar asked Jun 26 '15 17:06

thefistopher


People also ask

Why must await be in async function?

Use of async and await enables the use of ordinary try / catch blocks around asynchronous code. Note: The await keyword is only valid inside async functions within regular JavaScript code. If you use it outside of an async function's body, you will get a SyntaxError .

What happens if I don't await an async method?

async keyword doesn't do anything by itself. Each await gets combined into a AsyncStateMachine that can process stuff asynchronously. If you don't have await keyword inside async method then there is no reason to create AsyncStateMachine , so you get synchronous method. await is used to wait for a result to arrive.

Should you always await async methods?

If a method is declared async, make sure there is an await! If your code does not have an await in its body, the compiler will generate a warning but the state machine will be created nevertheless, adding unnecessary overhead for an operation that will actually never yield.

Is it OK to not await async?

Yes. If you don't need to wait, don't wait.


1 Answers

If you call an asynchronous method it will run asynchronously whether you await the returned task or not.

await doesn't affect how the method executes, only how you as the caller deals with it. You can call the async method, get the task and await it right away (which is the simplest option). That will enable you to write code that looks synchronous but runs asynchronously as await basically registers the rest of the code after it as a callback to be executed only after the awaited task is completed. This doesn't block in the traditional since as no thread is blocked, but the code flow will be sequential:

async Task LargerProcessAsync()
{
    if (condition)
    {
        await ReportSomethingHappenedAsync();
    }

    // do other stuff
}

However, you don't absolutely need to do that. You can get the task back, do other stuff and only then await it:

async Task LargerProcessAsync()
{
    Task task = null;
    if (condition)
    {
        task = ReportSomethingHappenedAsync();
    }

    // do other stuff

    if (task != null)
    {
        await task;
    }
}

Or you can simply remove the await completely. You should realize though that this can be dangerous as the task can be faulted and the exception can go unobserved and that's why it's discouraged. There are several ways to do this right, but they aren't simple. You can use Task.ContinueWith:

void LargerProcess()
{
    if (condition)
    {
        ReportSomethingHappenedAsync().ContinueWith(task => 
        {
            try
            {
                task.Wait();
            }
            catch (Exception exception)
            {
                // handle exception
            }
        })
    }

    // do other stuff
}

Or for ASP.Net look at Fire and Forget on ASP.NET

like image 137
i3arnon Avatar answered Oct 13 '22 14:10

i3arnon