andycruce Ответов: 1

Обновление winform из Нового потока


Я пытаюсь собирать данные в реальном времени из комбинации GPS/IMU и непрерывно отображать эту информацию на этикетке WinForm. Я буду получать данные GPS/IMU в основной программе, а затем запускать поток для отображения данных в режиме реального времени, в то время как основная программа продолжает собирать данные. Я смог сделать эту работу в коротком тестовом примере, но когда я расширил тест, чтобы поместить код потока в отдельный класс, у меня возникли проблемы. Сначала код, а потом я расскажу о проблемах:

Данные помещаются в свойства класса-код класса для этого:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Thread_Test_Sending_Data_to_Thread_Function
{
    public class FormData
    {
        public int Label1Data;
        public int Label2Data;
    }
}


Основной программой для сбора данных и запуска потока, который в настоящее время использует только набор данных, является:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;


namespace Thread_Test_Sending_Data_to_Thread_Function
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            int i;
            InitializeComponent();
            FormData FormData1 = new FormData();
            Thread1 MyThread = new Thread1();


            for (i = 1; i < 5; i++)
            {
                FormData1.Label1Data = i;
                FormData1.Label2Data = i * 10;
                Thread WriteScreen = new Thread(delegate ()
                {
                    MyThread.FormWriteMethod(FormData1, TestLabel1);
                });

                WriteScreen.Start();
                Thread.Sleep(1000);
            }
        }



   }

}


Код для класса thread выглядит следующим образом:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
using System.Windows.Forms;





namespace Thread_Test_Sending_Data_to_Thread_Function
{

    public class Thread1
    {
        int testInt1;
        int testInt2;
        int test;
        private delegate void SetLabelTextDelegate(FormData InputClass);
        public void FormWriteMethod(FormData InputClass, Label lbl)
        {
            testInt1 = InputClass.Label1Data;
            testInt2 = InputClass.Label2Data;
 
            UpdateLabel(lbl, InputClass.Label1Data.ToString());
        }
        void UpdateLabel(Label lbl, string text)

        {
            if (lbl.InvokeRequired)

            {
                lbl.Invoke(new Action<Label, string>(UpdateLabel), new object[] { lbl, text });
            }

            else
            {
                lbl.Text = text;
            }
            
        }
    }


Основываясь на использовании отладчика в VS, я почти уверен, что поток запускается правильно, так как код в потоке выполняется. Когда я впервые начал пытаться это сделать, я не передал метку для WinForm Label потоку, и попытка метода InvokeRequired привела к тому, что InvokeRequired не в контексте. Я добавил передачу метки в поток, а затем скомпилировал lbl.InvokeRequired. Однако он всегда указывает на ложь и lbl.Text = text; загружает этикетку, но ее содержимое не отображается до выхода из основной программы. Это означает, что даже после запуска нового потока этот поток все еще находится в основном потоке, который управляет графическим интерфейсом. Работали над этим несколько дней без каких-либо положительных результатов. Был бы признателен за любую помощь.

Что я уже пробовал:

Я попытался переместить код InvokeRequired в FormWriteMethod, чтобы посмотреть, не выйдет ли каким-то образом вызов второго метода из потока отображения и обратно в основной поток, но это, похоже, не помогло.

1 Ответов

Рейтинг:
1

Midi_Mick

Где это происходит неправильно, так это то, что ваш основной поток выполняет цикл и переходит в состояние ожидания (Sleep) на каждой итерации. Пока основной поток работает (в том числе в состоянии ожидания), он не может обрабатывать сообщения. Вам нужно либо поставить for зацикливайтесь на другом потоке или, что было бы лучше, избавьтесь от него совсем и поставьте код внутри из for петля, минус Sleep, в событие таймера.

Сама форма должна перекачивать свои сообщения, чтобы обновления происходили.


andycruce

Спасибо, я понимаю событие таймера. Как приостановить работу программы в WinForms? Для консольной процедуры вы просто ждете ввода консоли. Что можно сделать аналогично для WinForms?

Midi_Mick

В Winforms все, что вам нужно сделать, это убедиться, что ни один из ваших кодов не запущен. Пока форма отображается, она будет просто сидеть там, перекачивая сообщения. Только во время обработки события этот шаблон делает перерыв во время обработки события (то есть ваш код в форме выполняется).