2009-09-15 50 views
4

我有一個使用COM組件的C#應用​​程序。這個COM組件需要一個消息泵(Application.Run())來處理它。這意味着它一直卡在主線程上。但是我最近發現可以在另一個獲得自己的ApplicationContext的線程上啓動另一個Application.Run。沒有第二種形式的多線程消息抽取

所以我想在它自己的Application.Run()中的自己的線程上承載COM組件,但我無法弄清楚如何在不創建UI表單的情況下在新線程上啓動事物。

我需要與線程通信的WindowsFormsSynchronizationContext直到Application.Run()才被創建。但是一旦調用了Application.Run(),我就無法弄清楚如何獲取SynchronizationContext。如果我可以在該線程上引發單個事件,那麼我可以使用它來引導整個事物(創建COM對象等),但似乎沒有任何地方可以在沒有表單的情況下掛入新的事件循環。

我已經嘗試過各種令人費解的事情,比如安裝一個消息過濾器(在新線程中沒有提示消息),將執行上下文複製到另一個線程中並嘗試從那裏檢索SynchronizationContext(它拒絕複製一個已經運行的線程的ExecutionContext),在啓動Application.Run()之前檢索Thread.CurrentContext,然後調用DoCallbBack()(DoCallback在原始線程上結束)等等。

回答

6

布萊斯,

您也許能夠從Anders Hejlsberg's talk about "The Future of C#".適應這個片段中這是一個有點類,增加了一個消息泵線程,這樣他就可以使用REPL循環打開的窗戶,他們將有一個消息泵附在他們身上。

的代碼看起來是這樣的:

using System.Windows.Forms; 
using System.Threading; 
class UserInterfaceThread() 
{ 
    static Form window; 

    public UserInterfaceThread() 
    { 
     var thread = new Thread(() => { 
      window = new Form(); 
      var handle = window.Handle; 
      Application.Run(); 
      }); 
     thread.Start(); 
    } 
    public void Run(Action action) 
    { 
     window.Invoke(action); 
    } 
} 

與此代碼的討論發生後1小時到Anders的通話5分鐘,如果你想查看。

+0

所以事實證明,創建一個窗口句柄是實例化SynchronizationContext而不是Application.Run()。所以簡單地調用「IntPtr handle = new Form()。Handle;」在調用Application.Run()之前創建所需的WindowsFormsSynchronizationContext。非常感謝。 – 2009-09-15 17:02:09