C# 创建新的WindowsFormsSynchronizationContext

C# 创建新的WindowsFormsSynchronizationContext,c#,.net,winforms,multithreading,thread-safety,C#,.net,Winforms,Multithreading,Thread Safety,我在singleton类中有一个异步方法,需要在UI线程上触发事件,因为订阅事件的大多数人都是控件,但方法的调用方不是控件。因为调用者不是一个总是控制,我不能将它传递给UI线程调用,所以我在启动后台线程之前使用AsyncOperation/SynchronizationContext获取当前线程上下文,然后在后台线程中调用Post,有点像这样 public void AsyncMethod() { AsyncOperation ao = AsyncOperationManager.Cre

我在singleton类中有一个异步方法,需要在UI线程上触发事件,因为订阅事件的大多数人都是控件,但方法的调用方不是控件。因为调用者不是一个总是控制,我不能将它传递给UI线程调用,所以我在启动后台线程之前使用AsyncOperation/SynchronizationContext获取当前线程上下文,然后在后台线程中调用Post,有点像这样

public void AsyncMethod()
{
    AsyncOperation ao = AsyncOperationManager.CreateOperation(null);
    // or SynchronizationContext ctx = WindowsFormsSynchronizationContext.Current;

    ThreadPool.QueueUserWorkItem(delegate(objact state)
    {
        //do stuff
        ao.Post(delegate(object state2)
        {
            // fire event
        }, null);
    }, null);
}

问题是AsyncOperation有时会给我一个新的上下文,或者WindowsFormsSynchronizationContext为null。我发现其他人也有同样的问题,我认为这与创建控件的下拉菜单项有关,这将在事件中发生。无论如何,我的问题是,如果WindowsFormsSynchronizationContext为null,我是否可以创建一个新的来调用Post,并且这个新的是UI线程的上下文,还是创建它的线程的上下文?

如果这是UI应用中的一个单例,我建议保留一个在UI线程上创建的类型控件的私有成员,并将其用于所有调用:

  • 您可以要求从UI线程调用“initialize”方法(比如在Application.Run之前)并在那里实例化同步控件
  • 或者,您可以在第一次访问singleton时创建同步控件,方法是检查当前线程是否正在运行消息循环(使用Application.MessageLoop),或者不调用Application.OpenForms之一上的控件创建

  • 第一种方法更具确定性,因此建议使用。

    No,当从工作线程调用AsynchMethod()时会发生这种情况。NET行为是可以辩护的,但要证明它的合理性需要付出努力。然而,这确实表明应用程序中的线程正在失控。不要寻找解决方法(Application.OpenForms),找出线程调用此方法的原因。