Click here to Skip to main content
15,887,945 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I am trying to collect real time data from an GPS/IMU combination and display the information continuously in a WinForm Label. I will be getting the GPS/IMU data in the main program and then starting a thread to display the data in real time while the main program continues to collect the data. I was able to make this work in a short test case but when I expanded the test to put the thread code in a separate class I am having problems. First the code and then I'll cover the issues:

Data is placed in properties in a class-the class code for this is:

C#
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;
    }
}


The main program to collect the data and start the thread which is currently only using set data is:

C#
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);
            }
        }



   }

}


The code for the thread class is:
C#
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;
            }
            
        }
    }


Based on using the debugger in VS I am pretty sure the thread is being properly initiated in that the code in the thread runs. When I first started trying to do this I didn't pass the label for the WinForm Label the thread and trying the InvokeRequired method resulted in a InvokeRequired not in context. I added passing the label to the thread and then lbl.InvokeRequired compiled. However, it always indicates false and the lbl.Text=text; loads the label but the label contents are not displayed until the main program exits. This implies that even after starting the new thread that the thread is still in the main thread that controls the GUI. Have been working on this for days with no positive results. Would appreciate any help.

What I have tried:

I tried moving the InvokeRequired code to the FormWriteMethod to see if somehow calling a second method somehow got out of the display thread and back to the main thread but that didn't seem to help.
Posted
Updated 18-Nov-16 11:28am

1 solution

Where this is going wrong is that your main thread performing the loop, and going into a wait state (Sleep) on each iteration. While the main thread is running (including in the wait state), it is not able to process messages. You need to either put the for loop into another thread, or, which would be better, get rid of it altogether, and put the code inside of the for loop, minus the Sleep, into a timer event.

The form itself need to be pumping its messages for the updates to occur.
 
Share this answer
 
Comments
andycruce 18-Nov-16 18:23pm    
Thanks, I understand the timer event. How do I pause the program in WinForms. For a console routine you just wait for a console input. What is the similar thing to do for WinForms?
Midi_Mick 18-Nov-16 18:33pm    
In Winforms, all you need to do is make sure none of your code is running. So long as the form is displayed, it will just sit there pumping the messages. Only while processing an event does this pattern take a break while the event is being processed (i.e. your code in the form is running).

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900