Ускорение обновления Gui в реальном времени из потока - PullRequest
5 голосов
/ 25 апреля 2011

Это метод, который я использовал годами для получения сетевых данных и использования их в моем графическом интерфейсе (диалог, форма и т. Д.).

    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 # и заметил много других подобных способов сделать эту обработку данных. такие как рабочие потоки и другие способы использования Delegate и Invoke.

Мой вопрос ... Есть ли в более новых библиотеках .Net (3.5, 4.0 и т. Д.) Более эффективный способ получения данных / обновления графического интерфейса?

Я думаю, что этот метод не работает с C #.

Любая помощь будет оценена.

Ответы [ 2 ]

4 голосов
/ 25 апреля 2011

Один из лучших способов публикации обновлений в графическом интерфейсе состоит в том, чтобы рабочий поток упаковывал данные, включенные в обновление, и помещал их в очередь. Затем поток пользовательского интерфейса будет периодически опрашивать очередь. По моему мнению, использование рабочего потока Control.Invoke для обновления пользовательского интерфейса way слишком часто используется. Напротив, наличие опроса потока пользовательского интерфейса для обновлений имеет несколько преимуществ.

  • Это нарушает тесную связь между пользовательским интерфейсом и рабочими потоками, которые навязывает Control.Invoke.
  • Он возлагает ответственность за обновление потока пользовательского интерфейса на поток пользовательского интерфейса, к которому он все равно должен принадлежать.
  • Поток пользовательского интерфейса определяет, когда и как часто должно происходить обновление.
  • Нет риска переполнения насоса сообщений пользовательского интерфейса, как в случае с методами маршалинга, инициированными рабочим потоком.
  • Рабочему потоку не нужно ждать подтверждения того, что обновление было выполнено, прежде чем переходить к следующим шагам (т. Е. Вы получаете большую пропускную способность как для пользовательского интерфейса, так и для рабочих потоков).

Вы не упомянули, как был реализован ThreadOutput, но вы могли бы рассмотреть подход, о котором я упоминал выше, если это еще не сделано таким образом. Опыт научил меня, что обычно это лучший подход. Позволить потоку пользовательского интерфейса ограничить цикл обновления - большое преимущество.

1 голос
/ 25 апреля 2011

Взгляните на Пул потоков вместо того, чтобы каждый раз вращать новую нить.

...