Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can async methods have expensive code before the first 'await'?

Is it bad to have expensive code at the start of an async method, before the first await is called? Should this code be wrapped with a TaskEx.Run instead?

public async Task Foo()
{
    // Do some initial expensive stuff.
    // ...

    // First call to an async method with await.
    await DoSomethingAsync;
}
like image 921
Lawrence Wagerfield Avatar asked Dec 09 '11 17:12

Lawrence Wagerfield


People also ask

What happens when you call async method without await?

The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't expected.

Can async method have multiple awaits?

We start a timer, this will allow us to time the code to see how long the code will run for. The solution. In order to run multiple async/await calls in parallel, all we need to do is add the calls to an array, and then pass that array as an argument to Promise.

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.

Which is the recommended way to wait for an async method to complete?

No problem, just make a loop and call this function with an await: [code] for (int i = pendingList. Count - 1; i >= 0; i--)


2 Answers

As Reed says, it really depends on the context. The code has to run at some point - but depending on the context, it may end up being run on a thread pool thread instead of some critical one.

Rather than using Task.Run, I'd use TaskEx.Yield:

public async Task Foo()
{
    await TaskEx.Yield();
    // Do expensive stuff
}

As far as I'm aware, that's basically a way of immediately returning to the caller, but allowing the rest of the async method to be scheduled straightaway. If you're in something like a Windows Forms UI thread, there's no point in doing this as you'll be back to the UI thread (and running expensive code there) immediately - but it would make sense if you're in a context where the current thread shouldn't be blocked, but continuations are run on another thread.

like image 63
Jon Skeet Avatar answered Oct 30 '22 01:10

Jon Skeet


It's not necessarily bad, but it may have unexpected consequences. If the caller expects that the code will behave completely asynchronously, the expensive code will run synchronously. This will cause it to behave partly like a synchronous method, but also asynchronously, which is kind of the worst of both worlds (extra complexity from asynchrony without the repsoniveness...)

If possible, I would recommend trying to have as little "expensive" code leading to the first await. Using Task.Run (or TaskEx.Run in the CTP) to wrap the expensive code, or moving the expensive code into its own asynchronous method (upon which you could await) would be beneficial in this case.

like image 27
Reed Copsey Avatar answered Oct 30 '22 02:10

Reed Copsey