2013-07-16 74 views
2

在发布lambda表达式到当前WindowsFormsSynchronizationContext,我发现拉姆达代码执行在后台线程:WindowsFormsSynchronizationContext.Current.Post后台线程执行拉姆达

// 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

这突然发生的事情是以前有没有线程的问题,并没有被最近修改(解决方案的其他部分都)在窗体上。我试图寻找明显的错误(例如,在后台线程上实例化窗体本身的代码或在后台线程上创建的控件),但我一直未能找到明显的违规行为。

也许我在找错方向?

+0

'WindowsFormsSynchronizationContext.Current'将返回null从另一个线程查询时,你必须将其保存以备后用 –

+0

不是null;投射时它是空的。我会澄清,谢谢@Sriram。 – magma

+0

这将是空的,请澄清 –

回答

4

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

检查SynchronizationContext.Current.GetType()并且您会发现您正在不同的同步环境下运行。

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

+0

请问,如果你使用'通过衍生的基类的静态member'编译器警告? –

+0

@us确实,并创建一个'WindowsFormsSynchronizationContext上下文=新的WindowsFormsSynchronizationContext();'允许邮政按预期运行。现在我知道在哪里看,谢谢。 – magma

+2

事实证明,另一名开发人员在另一个WinForm中提交了一个流氓SynchronizationContext.SetSynchronizationContext调用。再次感谢您的帮助。 – magma