如何仅在客户端应用程序中使用SynchronizationContext

时间:2012-10-24 12:09:27

标签: c# asp.net synchronizationcontext

在我的库中,我使用SynchronizationContext使我能够轻松地在GUI线程上引发事件,无论该库是在Windows窗体还是WPF应用程序中使用。如果我的类是在后台线程上创建的,那么SynchronizationContext为null,所以我直接引发了该事件。

例如:

    private void RaisePlaybackStoppedEvent()
    {
        EventHandler handler = PlaybackStopped;
        if (handler != null)
        {
            if (this.syncContext == null)
            {
                handler(this, EventArgs.Empty);
            }
            else
            {
                this.syncContext.Post(state => handler(this, EventArgs.Empty), null);
            }
        }
    }

这很好,除了我有用户报告它在ASP.NET应用程序中出错:

System.NullReferenceException was unhandled
  Message=Object reference not set to an instance of an object.
  Source=System.Web
  StackTrace:
       at System.Web.HttpApplication.ThreadContext.Enter(Boolean setImpersonationContext)
       at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)
       at System.Web.AspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback callback, Object state)
       at System.Web.AspNetSynchronizationContext.CallCallback(SendOrPostCallback callback, Object state)
       at System.Web.AspNetSynchronizationContext.Post(SendOrPostCallback callback, Object state)

我假设ASP.NET网站中SynchronizationContext为空。我需要一种不使用SynchronizationContext的方法,如果它是AspNetSynchronizationContext的一个实例,虽然这样做会相当hacky,因为我没有引用System.Web而且它不是公开可见的类型。

我的问题是,确定我是否使用GUI(例如WinForms,WPF,WinRT)并且只在该设置中使用SynchronizationContext的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

这看起来像是ASP.NET中的一个错误:如果在相应的请求完成后使用AspNetSynchronizationContext,则HttpApplication已清除其_context字段。然后它将此null引用传递给ThreadContext构造函数,ThreadContext类上的方法尝试访问该字段的成员,从而导致NullReferenceException

我知道他们在4.5中对这个区域进行了一些更改,所以它可能已经修复了。如果没有,它可能值reporting on Connect

作为解决方法,您可以尝试检查当前SynchronizationContext的类型名称:

var context = SynchronizationContext.Current;
if (null != context && "AspNetSynchronizationContext" == context.GetType().Name)
{
   context = null;
}

this.syncContext = context;