2011-12-19 85 views
1

我一直以爲我可以使用SynchronizationContext來封送到另一個線程的調用。顯然我錯了,因爲SyncCtx.Send()除了調用給定的委託(停留在同一個線程上)之外什麼都不做。我是否真的需要從SynchronizationContext派生並在線程上下文中工作?我覺得想念一些東西。框架像線程編組

我想要的是什麼:想象一下在應用中執行命令的一點API。您也可以在後臺線程上執行命令,因爲您可以分配委託在命令執行完成後運行。這個「Call-me-when-done」-Delegate獲取包含成功/失敗標誌,可選異常信息等的單個參數(狀態)。我想在原始調用線程上調用此委託,以便使用lib的開發人員不會需要處理invoke需要的等。我只想把它拿走,讓他們做簡單的非線程感知編程。 WindowsFormsSynchronizationContext似乎沒有幫助,如果你不給它作爲目標的一些控制。

感謝您的幫助!

回答

0

當你在winforms中並且你使用synchronizationcontext時,這個調用將被編組到GUI線程中。

爲您的特定情況下,我想這樣的事情應該工作,因爲這可能是創建一個表示Command

public class CommandManager 
{ 
    private readonly SynchronizationContex _synchronizationContex; 

    public CommandManager(SynchronizationContext synchronizationContex) 
    { 
     _synchronizationContex = synchronizationContex; 
    } 

    public void ExecuteAsync(Func<State> action, Action<State> callback) 
    { 
     ThreadPool.QueueUserWorkItem(o => { 
              state = action(); 
              _synchronizationContex.Send(oo => callback(state)); 
              }); 
    } 
} 

你會創建這樣(在GUI線程類是一個好主意,因此,例如在主窗體)

var commandManager = new CommandManager(SynchronizationContext.Current); 

你會使用這樣的:

commandManager.ExecuteAsync(() => new State() { Success = true }, 
          c => MessageBox.Show("success in the GUI thread")); 
+0

他勞厄並感謝你的回答,但實際上你犯的錯誤是我犯的。 SynchronizationContext不會做任何事情。 Send只調用發送被調用 - > NO編組(使用反射器)的同一個線程上的委託。 WindowsFormsSynchronizationContext f.e.進行編組,但僅限於給定的目標控件。所以這也沒有幫助。 – Gope 2011-12-19 09:04:57

+0

@Gope'SynchronizationContext'只是'WindowsFormsSynchronizationContext'的基類,當你在一個winforms應用程序中'SynchronizationContext.Current'持有一個'WindowsFormsSynchronizationContext',因此會封送你的線程。你是如何得出你認爲它不是元帥的結論的? – 2011-12-19 09:10:35

+0

這很有趣!我正在研究這兩個類的代碼。我的整個代碼都在UnitTests中運行,因此我必須自己構建SyncCtx並檢查ManagedThreadIds。基類不是編組,可以通過代碼和生成的線程ID識別出來。我沒有想到在SC.Current內部放置WFSyncCtx的實例的框架......我會研究這一點,但是你所說的話是非常有意義的。我的測試課對我隱藏了一些東西。 :D 謝謝! – Gope 2011-12-19 09:30:46