Click here to Skip to main content
15,867,568 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I had tried background worker, thread and task but the procedure are so long to get a solution according to my question. suppose I use a task, I can't add any textboxes in ABC function which is called in button_click. When I use textbox inside button click function on the place of ABC function it's worked. But this process is not fulfil my requirement. If I called this function directly into buttonclick event it's hang my UI. Here is the example code of ABC function.

public void ABC()
        {
            While(true)
            {
              richTextBox1.AppendText("Hello");
              richTextBox2.AppendText("Tesing");
            }
        } 

If anyone have an idea to achieve this, please tell me.

I am trying this because my sensor gives me data on continuous basis and I used these values to draw a graph, so I tried to run that in background to update my graphs on continuous basis.

What I have tried:

I am posting original code here. Explanation: I have sensor which sends there data on API every 5 minutes in JSON format. Now my code fetching data from API and display a graph after button click. When I click on button my graph is updated with new data but I want to try to convert this manual process into automatic process. I mean when I click on button my function should have run continuously and update data on graph without hanging UI because I have to perform another operations on graph. Here is my function with original code:

C#
public void EnvlopGraph() {

        //while (true)
        //{
            graph = new Graph();
            //frmdeviceconfig deviceinfo = new frmdeviceconfig(this);
            grpboxselectaxis.Enabled = false;
            chkboxxaxis.Checked = true;
            chkboxyaxis.Checked = false;
            chkboxzaxis.Checked = false;
            frm.GetSensorId();
            frm.GetOverall();
            chartview1.Visible = true;
            grpboxselectaxis.Visible = true;
            double[] XAxisRange;

            envlpxfft.Clear();
            envlpyfft.Clear();
            envlpxtime.Clear();
            envlpytime.Clear();
            var client = new RestClient(frm.ClientURL);
            var request = new RestRequest($"api/traces", Method.GET);

            try
            {
                IRestResponse response = client.Execute(request);

                JsonDeserializer deserial = new JsonDeserializer();
                dynamic obj = deserial.Deserialize<dynamic>(response);

                var objindexcount = obj.Count;
                var TracesData = obj[objindexcount - 1];    //this is applicable on current Bearing data only
                //var TracesData = obj[objindexcount - 2];      // for current Tri_Acc Data (x,y,z)

                var SerialNumber = TracesData["serialNumber"];
                if (SerialNumber == frmdeviceconfig.stpointsensor)
                {
                    var RouteTime = TracesData["routeTime"];
                    var SampleTime = TracesData["sampleTime"];
                    var Name = TracesData["name"];
                    var SignalPath = TracesData["signalPath"];
                    var Range = TracesData["range"];
                    string SampleRate = TracesData["sampleRate"];
                    string[] SR = SampleRate.Split('S', 'a', 'm', 'p', 'l', 'e', 'R', 'a', 't', 'e', '_');
                    double SampleRateVal = Convert.ToDouble(SR[11]);
                    string TraceLength = TracesData["traceLength"];
                    var XAxisTrace = TracesData["xAxisTrace"];
                    string[] TL = TraceLength.Split('T', 'r', 'a', 'c', 'e', 'L', 'e', 'n', 'g', 't', 'h', '_');
                    double TraceLengthVal = Convert.ToDouble(TL[12]);
                    double xtimerange = Convert.ToDouble((TraceLengthVal / TraceLengthVal) / TraceLengthVal);
                    if (chartview1.Controls.Count > 0)
                    {
                        chartview1.Controls.Clear();
                        chartview1.Controls.Remove(graph);
                    }

                    if (XAxisTrace != null)
                    {
                        var XAdcRangePercent = XAxisTrace["adcRangePercent"];
                        var XClipped = XAxisTrace["clipped"];
                        var XRangeApplied = XAxisTrace["rangeApplied"];
                        var XGravityRemoved = XAxisTrace["gravityRemoved"];
                        var XTimeWave = XAxisTrace["timewave"];
                        var xaxisdatalength = XTimeWave.Count;
                        XData = new double[xaxisdatalength];
                        XAxisRange = new double[xaxisdatalength];

                        for (int i = 0; i < xaxisdatalength; i++)
                        {
                            XData[i] = XTimeWave[i];
                            XAxisRange[i] = i * xtimerange;
                        }
                        //Add graph
                        envlpxtime.Add(XAxisRange);
                        envlpytime.Add(XData);
                        if (Display == 1)
                        {
                            if (GraphType != "FFT")
                            {
                                graph.DrawLineGraph(envlpxtime, envlpytime);
                            }
                            else
                            {
                                //fft graph for x axis 
                                FFTConversion fft = new FFTConversion();
                                if (XData == null)
                                {
                                    MessageBox.Show("TimeData is not available");
                                }
                                else
                                {
                                    double[] fftdata = fft.ConvertTimeDataToFFT(XData);
                                    chartview1.Visible = true;
                                    string[] linekhz = Name.Split('B', '_', 'X', 'R', 'G', 'L', 'H');
                                    double lines = Convert.ToDouble(linekhz[8]);
                                    double hz = Convert.ToDouble(linekhz[10]);
                                    double fftXrange = hz / lines;
                                    for (int k = 0; k < fftdata.Length; k++)
                                    {
                                        XAxisRange[k] = k * fftXrange;
                                    }

                                    envlpxfft.Add(XAxisRange);
                                    envlpyfft.Add(fftdata);
                                    graph.DrawLineGraph(envlpxfft, envlpyfft);
                                }
                            }
                            graph.Dock = DockStyle.Fill;
                            chartview1.Controls.Add(graph);
                        }

                    }
                    else
                    {
                    }
                }
            }
            catch (Exception ex)
            {
            }
    }
Posted
Updated 4-Feb-22 20:03pm

1 solution

Your "small sample" of code will not work. You can't add an infinite amount of data to a Text box, Rich or not: each time you try, you create a new string which is longer than the last, and cause a Paint event to be queued on the TextBox - which will not be actioned until after your method returns control to the system, so you will never, ever see any text being added. In addition, you will rapidly run out of memory, and your app will crash.

You chart update works on a button because it's run once, and removes a Chart to replace it with another. That's not a "quick" operation, and as the amount of data rises, it becomes a longer and longer process, until at some point the time taken to ready a new chart for display will exceed the interval between updates and it will all start to fail or your UI will hang, or it will plain crash.

Instead of creating a new Chart each time consider either updating the chart data (which is quicker than creating a whole new control each time) or create your own control to display just your data - that can be more efficient than a Chart control because it isn't trying to work with "generic" data.

I'd start by thinking about what I want to display, and how I want to display it: is this "rolling data" which always displays the same number of points (a days worth, an hours worth, whatever) or data with just "grows continually" with new points being added each time?

Then I'd think about how I receive the data: is there an event which says "I have data for you" as there is with SerialPort and Sockets? If so, then that's the obvious way to "trigger" an update (though you may have to use some Invoke operation to get the display itself to update if it is processed off of the UI thread as SerialPort.DataRecieved is).
If not, then a Timer is the obvious way to go, provided you can ensure that the process of updating the display will take less than the timer tick period.

What it looks like from your code is that you've just found a way - any way - to display a graph full of data, and suddenly realized that you need it to update. But rather than think about why and then how, you've just gone "it works, I'll loop it" which isn't going to help. Almost certainly, your existing solution is going to have to be binned in favour of a more complex solution that fits the actual need instead of bodged round to "fix it for now".
Sorry - but that's what happens when requirements change dramatically!
 
Share this answer
 

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