NullReferenceException in System.Threading.Tasks calling HttpClient.GetAsync(url)

前端 未结 3 805
陌清茗
陌清茗 2020-12-29 09:24

I have a strange problem in my MVC 4.0 application. I use REST web services (Amazon Associate) . I created a method, which I use from everywhere. The shortened version is th

相关标签:
3条回答
  • 2020-12-29 10:08

    From the looks of it, your code can complete before one of the threads put to sleep in an exception event from the first try block are resolved, so after 5 minutes when they wake up, there isn't an original thread to rejoin resulting in a NullReferenceException from AssociateWithCurrentThread

    0 讨论(0)
  • 2020-12-29 10:10

    When I was getting the exception and call stack shown above, it was because I was trying to do a "fire and forget" execution using async, which was a really bad idea. I switched to spinning of a new thread for what I wanted and the crashes went away.

    0 讨论(0)
  • 2020-12-29 10:16

    Adding on to @kcar's answer, I had a very similar issue where there were multiple awaits on a code path that had a single method that was not awaited, like:

    public async Task JsonResult BookThing(InputModel model)
    {
        // Do some stuff
        thisIsAnAsyncMethod(Model model); // Fire and forget
        return Json(null);
    }
    
    protected async Task thisIsAnAsyncMethod(Model model)
    {
        await oneThing();
        await anotherThing();
        await somethingElse();
    }
    

    That caused awaits to randomly fail without letting me catch the Exception - because TPL was trying to rejoin a Context that had been nulled out, so it was throwing a NullReferenceException outside of try/catch.

    This is very hard to diagnose. In Production you won't see anything in try/catch, and in Visual Studio which await gets scheduled to rejoin the original context is somewhat random - it depends on what the TaskScheduler happens to decide to do.

    If you didn't want to fire and forget the obvious answer is to await the async method - you'll have a compiler warning reminding you to do so.

    If you did want to fire and forget the solution is to explicitly start a new Task. The best way to do that is covered in this answer about fire and forget Tasks.

    0 讨论(0)
提交回复
热议问题