从线程中加速实时Gui更新

时间:2011-04-24 23:46:04

标签: c# multithreading networking delegates invoke

这是我多年来用来接收网络数据并在我的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
        }
    }
 }

接收器每秒接收10到100条实时消息,通常更多。

我最近一直在研究.Net 4.0和C#,并注意到许多其他类似的方法来进行这种数据处理 ,例如Worker Threads,以及使用Delegate和Invoke的其他方法。

我的问题......在较新的.Net库(3.5,4.0等)中,是否有更有效的方法来进行数据接收/ GUI更新?

我认为这种方法与C#不一样。

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:4)

向GUI发布更新的最佳方法之一是让工作线程打包更新中包含的数据并将其放入队列中。然后,UI线程将定期轮询队列。在我看来,让工作线程使用Control.Invoke更新UI是方式过度使用。相比之下,对更新进行UI线程轮询有几个优点。

  • 它打破了Control.Invoke强加的UI和工作线程之间的紧密耦合。
  • 它将更新UI线程的责任放在它应该属于的UI线程上。
  • UI线程决定更新的发生时间和频率。
  • UI消息泵没有溢出的风险,就像工作线程启动的编组技术一样。
  • 在继续执行下一步之前,工作线程不必等待确认已执行更新(即,您在UI和工作线程上获得更多吞吐量)。

你没有提到ThreadOutput是如何实现的,但你可能会考虑我上面提到的方法,如果还没有这样做的话。经验告诉我,这通常是最好的方法。让UI线程限制其更新周期是一个很大的优势。

答案 1 :(得分:1)

每次都要查看Thread Pooling而不是旋转新主题。