9

I'm currently having issues with IIS crashing out leaving the following messages in the event log. They're not too helpful in directing me to the actual source of the error but a bit of research suggests this is just a case of spawning tasks but not waiting for the result, when they do eventually complete if the parent process has completed it cannot be associated with the parent thread which causes a null reference exception. Is that correct?

For the most part I have removed or added awaits where this was going on but there are some areas where it is handy. One such example is on session start is memory caching a few details unique to the session, however they're not vital immediately so I spin up a task to do this work but don't await it.

I have added ConfigureAwait(false), is this sufficient to prevent the error in future? It sounds like this will remove the thread switching which I assume will prevent the error.

Task.Run(() =>
{
    // Do caching here

}).ConfigureAwait(false);

ASP.NET 4.0.30319.0

Exception: System.NullReferenceException

Message: Object reference not set to an instance of an object.

StackTrace:    at System.Web.ThreadContext.AssociateWithCurrentThread(Boolean setImpersonationContext)
   at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)
   at System.Web.LegacyAspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback callback, Object state)
   at System.Web.LegacyAspNetSynchronizationContext.CallCallback(SendOrPostCallback callback, Object state)
   at System.Threading.Tasks.AwaitTaskContinuation.RunCallback(ContextCallback callback, Object state, Task& currentTask)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.Tasks.AwaitTaskContinuation.<ThrowAsyncIfNecessary>b__1(Object s)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()

.NET Runtime

Application: w3wp.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.NullReferenceException
Stack:
   at System.Threading.Tasks.AwaitTaskContinuation.<ThrowAsyncIfNecessary>b__1(System.Object)
   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()

Application Error

Faulting application name: w3wp.exe, version: 7.5.7601.17514, time stamp: 0x4ce7afa2
Faulting module name: KERNELBASE.dll, version: 6.1.7601.18015, time stamp: 0x50b8479b
Exception code: 0xe0434352
Fault offset: 0x0000000000009e5d
Faulting process id: 0x1d98
Faulting application start time: 0x01ceaf8ea10ece66
Faulting application path: c:\windows\system32\inetsrv\w3wp.exe
Faulting module path: C:\Windows\system32\KERNELBASE.dll
Report Id: 341b9a76-1b82-11e3-8e17-005056be0005
Community
  • 1
  • 1
Hawxby
  • 2,746
  • 21
  • 29
  • `ConfigureAwait()` doesn't make any sense without `await`. – svick Sep 12 '13 at 10:02
  • Would it make more sense to use ThreadPool.QueueUserWorkItem? – Hawxby Sep 12 '13 at 10:38
  • IIS schedules handling of requests to the .NET thread pool. Unless you are doing parallel work in the same request, using `Task.Run` and `ThreadPool.QueueUserWorkItem` will hurt the performance of every running request because it will be performing unnecessary context switching. – Paulo Morgado Mar 10 '14 at 17:34

1 Answers1

6

After a morning of chasing this problem around I eventually discovered there was a path which could allow for the parent to bypass the await creating this problem. A quick refactoring to prevent this solved the problem.

In its most simple form the code causing the problem was along the lines of this:

var getDataTask = getData();

if(some_condition == true) {
    return some_object;
}

getDataTask.Wait();

return getDataTask.result;

If some_condition == true the method would return without waiting for getDataTask to complete. Refactoring to stop that fixed it.

abdullahalali
  • 396
  • 2
  • 5
  • 18
Hawxby
  • 2,746
  • 21
  • 29
  • I'm also suffering this same exception randomly. Can you provide some more details, please? What does your code messed up look like? – deerchao Dec 20 '13 at 16:15
  • 3
    I wouldn't recommend this code. You still have a fire-and-forget code path, which is dangerous is a web app, plus you have introduced a blocking call with Wait(). Is getData() really doing something so time-consuming that awaiting it is not an option? Also, is there any significant CPU or I/O intensive work that needs to be done to come up with the value of "some_condition" or is it just a simple check against some value you already have? – Todd Menier Dec 30 '13 at 16:28
  • 3
    Sorry I should clarify, I'm not recommending it either, that was the code causing the problem – Hawxby Dec 30 '13 at 18:00