2013-07-16 71 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