创建新的WindowsFormsSynchronizationContext

时间:2011-02-17 05:25:30

标签: c# .net winforms multithreading thread-safety

我在单例类中有一个异步方法需要在UI线程上触发事件,因为订阅该事件的大多数人都是控件,但该方法的调用者不是控件。因为调用者不是一个总是控件我无法将其传递回Invint回到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 on,并且新的那个是UI线程的上下文,还是创建它的线程的上下文?

1 个答案:

答案 0 :(得分:1)

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

  1. 您可以要求从UI线程调用“初始化”方法(比如在Application.Run之前)并实例化同步控制
  2. 或者,您可以在首次访问单例时创建同步控件,方法是检查当前线程是否正在运行消息循环(使用Application.MessageLoop),以及是否在Application.OpenForms之一上调用控件创建。 / LI>

    第一种方式更具确定性,因此被推荐。