【问题标题】:WindowsFormsSynchronizationContext.Current.Post executes lambda on background threadWindowsFormsSynchronizationContext.Current.Post 在后台线程上执行 lambda
【发布时间】:2013-07-16 13:18:08
【问题描述】:

在向当前WindowsFormsSynchronizationContext 发布 lambda 表达式时,我发现 lambda 代码在后台线程上执行:

// running on main thread here

myLabel = new Label();
this.Controls.Add(myLabel);

WindowsFormsSynchronizationContext.Current.Post( ignore => {

    // returns true !
    bool invokeRequired = myLabel.InvokeRequired; 

    // returns a background thread, not the UI thread
    int threadId = System.Threading.Thread.CurrentThread.ManagedThreadId; 

    // throws, because we are (unexpectedly) on a background, different thread
    myLabel.Text = "whatever";

},null);

此外,WindowsFormsSynchronizationContext.Current 似乎返回的不是WindowsFormsSynchronizationContext,而是一个普通的System.Threading.SynchronizationContext

这突然发生在一个过去没有线程问题并且最近没有修改过的表单上(解决方案的其他部分是)。我尝试寻找明显的错误(例如,在后台线程上实例化表单本身的代码,或在后台线程上创建的控件),但我无法找到明显的违规行为。

也许我看错了方向?

【问题讨论】:

  • WindowsFormsSynchronizationContext.Current 从另一个线程查询时会返回 null,您必须保存以备后用
  • 不为空;施法时为空。我会澄清的,谢谢@Sriram。
  • 它将为空,请澄清
  • @SriramSakthivel 很清楚:提供给Post 的委托实际上被调用了,因此有一个SynchronizationContext。问题是从该委托访问 UI 失败,因为它没有在 UI 线程上运行。
  • @magma SynchronizationContext.Current.GetType() 在调试器中为您提供什么?

标签: c# multithreading winforms


【解决方案1】:

WindowsFormsSynchronizationContext.CurrentSynchronizationContext.Current 相同。您应该会收到编译器警告,提示您正在通过派生类调用基本静态成员。

检查SynchronizationContext.Current.GetType(),您会发现您在不同的同步上下文中运行。

在 UI 线程上捕获正确的上下文并将其存储。

【讨论】:

  • 如果通过 Derived 使用Base class static member,编译器是否会发出警告?
  • @usr 确实如此,并且创建 WindowsFormsSynchronizationContext context = new WindowsFormsSynchronizationContext(); 允许 Post 按预期运行。现在我知道去哪里找了,谢谢。
  • 事实证明,另一个开发人员在不同的 WinForm 中提交了恶意 SynchronizationContext.SetSynchronizationContext 调用。再次感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2012-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多