11

我正在尝试使用 AsyncTargetingPack 将一些信息异步记录到针对 .NET 4.0 的 MVC 4 控制器操作内的 SQL Server。我会直接跳到 .NET 4.5,但我的应用程序存在于 Azure 中,我们仍在等待更新......

此代码按预期工作(将一行写入我的数据库,没有抛出异常):

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));
    }
}

这段代码抛出了 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:“对象引用未设置为对象的实例。”

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()

我看不到异常,因为它都是外部代码。我不明白为什么第二个代码块会失败。这是我最初编写的代码。

我究竟做错了什么?

4

3 回答 3

7

我只是遇到了一个非常相似的问题(使用日志记录任务时来自 AssociateWithCurrentThread 的 NullReference)。

我遇到的问题是原始操作没有等待日志记录任务的完成,因此当日志完成并尝试重新加入原始线程时,会抛出 nullReference,因为原始线程已终止。

通过确保请求控制器等待日志记录功能,我解决了这个问题。

于 2013-05-17T18:52:43.510 回答
0

数据流仅适用于 .NET 4.5。您在 .NET 4.0 上运行它的事实不受支持,这可能是您看到虚假异常的原因。

于 2012-12-31T17:32:08.873 回答
-2

当我的 Web 服务以异步方式调用另一个 WCF 服务时,我遇到了 .net4.5 的这个问题。我只是附加了一个短时间Wait(),因为我不关心响应(遥测事件)。

public static void Event(string key, string message) {
    Telemetry.Event(key, message).Wait(100);
}
于 2014-06-06T23:37:33.027 回答