2010-04-07 82 views
1

我需要在我的課程中執行「Invoke()」方法,其行爲與Control.Invoke()一樣。如何在自定義類型中實現Control.Invoke模擬?

所以,當我從從創建實例線程不同的線程我InvokableEntity類的實例的工作,我將能夠調用invokableEntity.Invoke(代表委託會在InvokableEntity的線程實例的上下文中執行是在創建。

是的,我讀過this問題,它不會幫助我=(

請看看他的代碼,它說明我嘗試實施事件處理程序描述的行爲(CustomProcessor_ProgressChanged方法應該從線程它被訂閱的情況下被執行,但我不能這樣做):

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.ComponentModel; 
using System.Windows.Forms; 

namespace MultiThread 
{ 
    class Program 
    { 
     private static CustomProcessor customProcessor = new CustomProcessor(); 

     static void Main(string[] args) 
     { 
      Console.WriteLine("Worker was run from thread: {0}", Thread.CurrentThread.ManagedThreadId); 
      customProcessor.ProgressChanged += new EventHandler(CustomProcessor_ProgressChanged); 

      Thread workerThread = new Thread(customProcessor.Process); 
      AsyncOperation asyncOperation = AsyncOperationManager.CreateOperation(null); 
      //SynchronizationContext context = SynchronizationContext.Current; 
      workerThread.Start(asyncOperation); 

      Console.ReadLine(); 
     } 

     static void CustomProcessor_ProgressChanged(object sender, EventArgs e) 
     { 
      Console.WriteLine("Custom ProgressChanged was handled in thread: {0}", Thread.CurrentThread.ManagedThreadId); 
     } 
    } 

    class CustomProcessor 
    { 
     public event EventHandler ProgressChanged; 

     public void RaiseProcessChanged(object o) 
     { 
      Console.WriteLine("RaiseProgressChanged was handled in thread: {0}", Thread.CurrentThread.ManagedThreadId); 
      if (this.ProgressChanged != null) 
      { 
       this.ProgressChanged(this, EventArgs.Empty); 
      } 
     } 

     public void Process(object asyncOperation) 
     { 
      Console.WriteLine("CustomProcessor.Process method was executed in thread: {0}", Thread.CurrentThread.ManagedThreadId); 

      AsyncOperation asyncOperationInternal = (AsyncOperation)asyncOperation; 
      asyncOperationInternal.Post(this.RaiseProcessChanged, null); 

      //SynchronizationContext context = (SynchronizationContext) asyncOperation; 
      //context.Send(s => this.RaiseProcessChanged(null), null); 

      //this.RaiseProcessChanged(new object()); 
     } 
    } 
} 

謝謝!

+0

爲什麼沒有這個問題(+一些很好的答案)可以幫助你? – 2010-04-07 09:18:51

+0

它只是不適合我,我不能得到可行的解決方案。調用總是在不同的線程中執行=( – Restuta 2010-04-07 09:25:12

+0

顯示一些代碼 – 2010-04-07 09:27:51

回答

2

Control.Invoke()使用PostMessage() API調用來發布將由主GUI線程的消息泵使用的消息。

讓我們假設你在Thread#1創建CustomProcessor實例,它是不是一個GUI線程和創建的CustomProcessor的實例後,Thread#1那張具有悠久處理操作。如果您需要Invoke操作上Thread#1,你不想放棄當前的操作,這是一個好主意,而不是排隊將由Thread#1每次消耗Thread#1完成任務的工作項。
如果沒有邏輯排入從其它線程和出隊新的工作和內Thread#1處理它,它不會神奇的工作外的開箱。

如果您在沒有消息泵的多個線程上需要此功能,並且自定義類型不是從Control派生的,則可能會實現消息隊列或等效項。這樣,創建線程將在消息/工作隊列循環中消耗其大部分時間,等待新工作 - 就像調用Application.Run()時Windows窗體應用程序中的主GUI線程一樣。這可能不是你想要的。

+0

非常感謝,你給了我一個輝煌的解釋! – Restuta 2010-04-07 13:37:34

2

編組從一個線程到另一個電話是一個相當大的把戲。所需要的是一種機制,可以確保目標線程處於空閒狀態,並且可以運行執行請求,而不會有任何令人討厭的重入問題的危險。

的的SynchronizationContext類是這樣的機制的基類。它的默認實現並不實際同步任何東西,它在線程池線程上運行委託目標。

Windows窗體提供了一個類,做你正在尋找的東西,這WindowsFormsSynchronizationContext類。它依賴Application類中的消息循環來提供同步。這個類的一個實例被自動安裝,Application.Run()方法負責處理它。 WPF也有一個DispatcherSynchronizationContext。

問題是:你永遠不會被調用Application.Run()和你不運行的消息循環。所需的管道缺失。沒有那個消息循環,你就無法得到你想要的東西。

+0

謝謝你,你的解釋也很有幫助,謝謝你的時間! – Restuta 2010-04-07 13:38:05

相關問題