Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it OK to return from an async method before the final await?

I have a web page (aspx) that calls an async method in a class. The async method looks something like this:

public async Task<MyThing> GetMyThing()
{
    MyThing thing = new MyThing();
    var stuff = await Repository.GetStuff();
    // apply stuff to thing.

    var morestuff = await Repository.GetMoreStuff();
    // apply more stuff to thing.

    if (someCondition)
    {
        return thing;
    }

    var yetMoreStuff = await Repository.GetYetMoreStuff();
    // apply yet more stuff

    return thing;
}

If the condition is met, I don't need the data from the last repository call. Is the return before the final await going to cause me problems?

The reason I ask is I'm getting this error in the server application log, and I'm hunting for causes...

Application: w3wp.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.NullReferenceException
   at System.Web.ThreadContext.AssociateWithCurrentThread(Boolean)
   at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean)
   at System.Web.LegacyAspNetSynchronizationContext.CallCallbackPossiblyUnderLock(System.Threading.SendOrPostCallback, System.Object)
   at System.Web.LegacyAspNetSynchronizationContext.CallCallback(System.Threading.SendOrPostCallback, System.Object)
   at System.Threading.Tasks.AwaitTaskContinuation.RunCallback(System.Threading.ContextCallback, System.Object, System.Threading.Tasks.Task ByRef)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
like image 328
Elton Avatar asked Mar 08 '23 09:03

Elton


1 Answers

Yes, it is perfectly fine to not run certain async operations. What you have is fine. What would not be so fine would be:

var notYetAwaited = DoSomethingAsync();

if (done) return "yay!";

await notYetAwaited;

i.e. an async operation that spans the return. This has less obvious and predictable behaviour, especially in sync-context environments.

Your problem is unlikely to be because of the return. It sounds like this is simply a NRE happening in your data code that is being surfaced in the sync-context callback.

like image 105
Marc Gravell Avatar answered May 08 '23 03:05

Marc Gravell