从线程中加速实时Gui更新

Sle*_*eff 5 c# networking multithreading 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
        }
    }
 }
Run Code Online (Sandbox Code Playgroud)

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

我最近一直在研究.Net 4.0和C#,并注意到许多其他类似的方法来执行此数据处理,例如工作线程,以及使用Delegate和Invoke的其他方法.

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

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

任何帮助,将不胜感激.

Bri*_*eon 4

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

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

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