2011-04-24 123 views
5

這加快實時更新桂是我已經使用多年接收網絡數據,並在我的GUI使用它(對話,形成等)的技術。從一個線程

public delegate void mydelegate(Byte[] message); 

    public ReceiveEngineCS(String LocalIpIn, String ReceiveFromIp, mydelegate d) 
    { 
     this.m_LocalIpIn = LocalIpIn; 
     this.m_ReceiveFromIp = ReceiveFromIp; 
     m_MainCallback = d; 
     SetupReceive(); 
     m_Running = true; 
     //Create the Track receive thread and pass the parent (this) 
     m_RtdirReceiveThread = new Thread(new ParameterizedThreadStart(MessageRecieveThread)); 
     m_RtdirReceiveThread.Start(this); 
    } 

    private void MessageRecieveThread(System.Object obj) 
    { 
     ReceiveEngineCS parent = (ReceiveEngineCS)obj; 

     while(parent.m_Running) 
     { 
       Byte[] receiveBytes = new Byte[1500]; 
       try 
       { 
        receiveBytes = parent.m_ClientReceiver.Receive(ref parent.ipEndPoint); 
        parent.ThreadOutput(receiveBytes); 
       } 
       catch (Exception e) 
       { 
        parent.StatusUpdate(e.ToString()); 
       }       
     }   
    } 

    public void ThreadOutput(Byte[] message) 
    { 
     m_MainCallback(message);   
    } 

public partial class SystemMain : Form 
{ 
    //Local Class Variables 
    Network.ReceiveEngineCS SystemMessageReceiver; 
    private void Form1_Load(object sender, EventArgs e) 
    { 
     //Load up the message receiver 
     SystemMessageReceiver = new Network.ReceiveEngineCS(localAddy, fromAddy, new mydelegate(LocalDelegate)); 
    } 

    public void LocalDelegate(Byte[] message) 
    { 
     if (Form.ListView.InvokeRequired) 
     { 
      //External call: invoke delegate 
      Form.ListView.Invoke(new mydelegate(this.LocalDelegate), message); 
     } 
     else 
     { 
      //Get the Packet Header 
      Formats.PacketHeaderObject ph = new Formats.PacketHeaderObject(message); 
      //Update or Add item to Specific ListView 
      ... update views 
     } 
    } 
} 

Receiver每秒接收10到100個實時消息,並且通常更多。

我一直在做研究最近到.NET 4.0和C#,發現許多其他類似的方式來做到這一點的數據處理 ,比如工作線程,並使用代表和調用的其他方式。

我的問題...有沒有在新的.NET庫(3.5,4.0等)更有效的方式這個數據接收/ GUI更新呢?

我覺得這個方法不使用C#的工作,以及。

任何幫助,將不勝感激。

+1

每秒向用戶投擲100個通知沒有多大意義。它看起來像模糊。先讓你的UI可用,也解決你的問題。 Winforms沒有變化。 – 2011-04-25 00:18:48

+0

好主意漢斯。如果我在線程中構建關於傳入數據的元數據,並且每秒鐘只更新gui,那麼它仍然會給予用戶有關數據的體面迴應,同時允許Gui不會因更新而停滯不前。通常操作員使用更新數據項的粗略計數作爲數據速率的指導。因此,一眼就可以計算出十秒一秒50等等。但我可以將它作爲元更新並將其添加到列表視圖中。 – Sleff 2011-04-25 02:53:47

回答

4

一個更新發布到GUI的最好的方法是讓工作線程包了包含在更新的數據,並將其放置在隊列中。 UI線程將定期輪詢隊列。有工作者線程使用Control.Invoke更新UI是方式在我看來過度使用。相比之下,讓UI線程輪詢更新有幾個優點。

  • 它打破了用戶界面和工作者線程之間的緊密耦合,這些線程與Control.Invoke強加。
  • 它將UI線程更新的責任置於UI線程上,無論如何它應該屬於它。
  • UI線程可以決定更新應該發生的時間和頻率。
  • 不存在UI消息泵被超載的風險,這與工作線程啓動的封送處理技術的情況相同。
  • 工作線程不必等待確認該更新與它的下一個步驟之前執行(即你同時在用戶界面和工作線程的詳細吞吐量)。

你沒有提到ThreadOutput是如何實現的,但你可以考慮我上面提到的,如果它尚未做到這一點的方式方法。經驗告訴我,這通常是最好的方法。讓UI線程節制其更新週期是一大優勢。

+0

我一直用共享資源輪詢數據的問題一直是時機之一。鎖定和解鎖共享隊列會導致大量開銷(當然,我不會遇到這個問題)。我查看了工作線程,發現有線程發送更新的機制。我不確定是否必須使用調用工作線程來更新擁有UI的隊列? – Sleff 2011-04-25 03:05:02

+0

與'Control.Invoke'相比,隊列的鎖定是一件非常昂貴的操作。另外,你總是可以使用'ConcurrentQueue',它使用無鎖機制。工作線程不必使用'Invoke'將某些東西發佈到隊列中。首先將其稱爲「UI擁有隊列」可能有點誤導。 – 2011-04-25 12:54:35

+0

這有助於@布萊恩。我不確定調用的費用。我一直看到它用於從簡單文件或低速率xml數據更新gui的簡單示例中。我將檢查ConcurrentQueue,並考慮減少@Hans建議的需要更新的內容。 – Sleff 2011-04-25 16:27:40

1

看看到Thread Pooling而不是每次紡紗新的線程。

+0

謝謝贊博尼,但我實際上只使用一個線程的消息接收應用程序的整個生命週期。這些消息是我需要始終接收的事件的連續更新。 – Sleff 2011-04-25 02:46:39