【问题标题】:How do I use a SynchronizationContext only in client apps如何仅在客户端应用程序中使用 SynchronizationContext
【发布时间】:2012-10-24 12:09:26
【问题描述】:

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

例如:

    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)

我曾假设SynchronizationContext 在 ASP.NET 网站中为空。如果 SynchronizationContext 是 AspNetSynchronizationContext 的一个实例,我需要一种不使用它的方法,尽管这样做会很麻烦,因为我没有引用 System.Web,而且它也不是公开可见的类型。

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

【问题讨论】:

    标签: c# asp.net synchronizationcontext


    【解决方案1】:

    这看起来像 ASP.NET 中的一个错误:如果在相应请求完成后使用 AspNetSynchronizationContext,则 HttpApplication 已清除其 _context 字段。然后它将这个空引用传递给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;
    

    【讨论】:

    • 谢谢,这为我指明了方向。该请求几乎可以肯定已经完成,因为我的库是用于音频播放的,因此该事件可能会在播放开始后几分钟被触发(不太确定人们为什么要在他们的网络服务器上播放音频,但这就是我的一些用户正在做)。我想我将不得不使用您的解决方法,除非有更好的方法可以知道我是否在 ASP.NET 应用程序中。
    • 听起来你的用户肯定做错了什么——除非他们试图吓到你的系统管理员,否则谁会听到播放的声音?服务器还有声卡吗?他们可能希望声音在 client 上播放,但不了解其中的区别。你可能想检查Environment.UserInteractive,如果它返回false,则要么抛出异常,要么什么都不做。
    • 是的,这是一个奇怪的要求,但我确实不时让人们尝试这样做。 Environment.UserInteractive 看起来对我也有用。
    猜你喜欢
    • 2019-05-11
    • 1970-01-01
    • 2012-11-21
    • 2015-06-02
    • 1970-01-01
    • 1970-01-01
    • 2020-09-18
    • 2019-07-28
    • 1970-01-01
    相关资源
    最近更新 更多