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