Async logging throwing a NullReferenceException

点点圈 提交于 2020-01-21 03:06:27

问题


I am trying to asynchronously log some information to SQL Server inside of an MVC 4 controller action targeting .NET 4.0 using the AsyncTargetingPack. I would jump straight to .NET 4.5 but my app lives in Azure and we're still waiting for the update...

This code works as expected (a row is written to my database with no exceptions thrown):

public class SystemActionLogger : ISystemActionLogger
{
    private readonly ActionBlock<Tuple<SystemAction, object>> actionBlock;

    public SystemActionLogger(ISystemActionLogEntryRepository repository)
    {
        actionBlock = new ActionBlock<Tuple<SystemAction, object>>(
            entry => TaskEx.Run(async () =>
                {
                    string data = await JsonConvert.SerializeObjectAsync(entry.Item2);
                    await repository.PersistAsync(new SystemActionLogEntry(entry.Item1, data));
                }));
    }

    public void Log(SystemAction systemAction, object data)
    {
        actionBlock.Post(new Tuple<SystemAction, object>(systemAction, data));
    }
}

And this code throws a NullReferenceException:

public class SystemActionLogger : ISystemActionLogger
{
    private readonly ActionBlock<Tuple<SystemAction, object>> actionBlock;

    public SystemActionLogger(ISystemActionLogEntryRepository repository)
    {
        actionBlock = new ActionBlock<Tuple<SystemAction, object>>(async entry =>
            {
                string data = await JsonConvert.SerializeObjectAsync(entry.Item2);
                await repository.PersistAsync(new SystemActionLogEntry(entry.Item1, data));
            });
    }

    public void Log(SystemAction systemAction, object data)
    {
        actionBlock.Post(new Tuple<SystemAction, object>(systemAction, data));
    }
}

NullReferenceException: "Object reference not set to an instance of an object."

Server stack trace: 
   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.Runtime.CompilerServices.TaskAwaiter.<>c__DisplayClassa.<OnCompletedInternal>b__0(Task param0)

Exception rethrown at [0]: 
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__1(Object state)
   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()

I have no visibility into the exception as it is all external code. I don't understand why the second block of code fails. This is the code I originally wrote.

What am I doing wrong?


回答1:


I was just having a very similar issue (NullReference from AssociateWithCurrentThread when using a logging task).

The issue I was having was that the original action did not await the completion of the logging task, so when the log finishes and tries to rejoin the original thread a nullReference is thrown because the original thread has terminated.

This was solved for me by making sure that the request controller awaited the logging function.




回答2:


Dataflow only works on .NET 4.5. The fact that you're running it on .NET 4.0 is unsupported and is likely why you're seeing spurious exceptions.




回答3:


I had this problem with .net4.5 when my web service was invoking another WCF service in an async manner. I simply appended a short timed Wait() as I didn't care about the response (telemetry event).

public static void Event(string key, string message) {
    Telemetry.Event(key, message).Wait(100);
}


来源:https://stackoverflow.com/questions/12969071/async-logging-throwing-a-nullreferenceexception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!