0

Good day,

After being unsuccessful in my Google & Stackoverflow queries (not sure what I should search for), I'm posting here a public question.

I have a main form (frmMainMenu). Whenever this form is loaded and a button on this form is pressed, I'm trying to update a chart. However, as this could be CPU-demanding, I was considering calling the operation to retrieve the chart from another thread.

I'm constantly getting an error : Cross-thread operation not valid: Control 'labelX2' accessed from a thread other than the thread it was created on. System.Windows.Forms at System.Windows.Forms.Control.get_Handle()

The idea behind is also to display this symbol (referenced as the circularProgress1 control enter image description here whenever data is being retrieved and to hide it whenever the operation is complete.

Here below is the code of my method in the userform :

[...]

private void feedDashboard()
{

Thread l_Thread;
ClsStartPgm l_Start = null;
try
{
  this.Invoke(new MethodInvoker(delegate()
  {
    l_Thread = new Thread(() =>
    {
      try
      {
        l_Start = new ClsStartPgm();
        l_Start.getDashboardInformations(
        this.labelX2, 
        this.circularProgress1, 
        this.tmr_Progress,
        this.chart1, 
        this.expandablePanel_1);
      }
    finally
    {
      // onCompleted();
    }
  });
  
  l_Thread.Start();
  }));
}
catch (Exception exc)
{
  ClsFinappErrorManager.manageException(exc);
}

finally
{
}
}
[...]

and if it can be helpful, here is my mentioned getDashboardInformations method of my Class ClsStartPgm

public sealed class ClsStartPgm
{

[...] 
// (Constructors, accessors and other methods not mentioned here 
// to simplify the reading of my question)
[...] 

    public void getDashboardInformations(
    LabelX pInformationText, 
    Controls.CircularProgress pCircularProgress, 
    System.Windows.Forms.Timer pTimer,
    Chart pChart1, 
    ExpandablePanel pExpandablePanel1)
    {
        List<double> l_DoubleList = null;
        List<string> l_StringList = null;

        try
        {
            pTimer.Start();
            
            this.m_Busy_Dashboard_Generation = true;

            this.m_Busy_Dashboard_Generation = false;
            
            double[] yValues = l_DoubleList.ToArray();
            string[] xValues = l_StringList.ToArray();

            pChart1.Series["MySerie"].Points.Clear();

            // Populate series data
            pChart1.Series["MySerie"].Points.DataBindXY(xValues, yValues);

            // Set Doughnut chart type
            pChart1.Series["MySerie"].ChartType = SeriesChartType.Pie;
            
            // Set title of the expendable panel
            pExpandablePanel1.TitleText = "Situation: " + DateTime.Now.ToShortDateString();

            [...]
        }
        catch (Exception exc)
        {
            ClsFinappErrorManager.manageException(exc);
        }

        finally
        {
            l_Tuple = null;
            l_Accounts = null;
        }
    }
}

Please, could anyone guide me on what's wrong in my code? I'm definitely not asking to get the code written for me. However, I would be keen on understanding what I'm doing incorrectly here in my approach.

Many thanks for your appreciated help and best wishes,

Laurent
  • 711
  • 2
  • 12
  • 30
  • See if this answer is helpful: https://stackoverflow.com/a/39514556/9282880 – Gec Jun 12 '22 at 12:30
  • Does this answer your question? [Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on](https://stackoverflow.com/questions/142003/cross-thread-operation-not-valid-control-accessed-from-a-thread-other-than-the) – JonasH Jun 12 '22 at 12:33
  • Thank you Gec. So I was quite OK to use the "Invoke" method. But, how do I make the link between the start and the end of the event. In other words, how do I know when I can hide the circular progressbar? – Laurent Jun 12 '22 at 12:34
  • The simple answer is that *UI objects can only be accessed by the UI thread*. And this has been explained in numerous answers. So there is no guarantee that it is possible to create the chart on a background thread. You could still *fetch* the data in the background, and do the UI updates on the UI thread. – JonasH Jun 12 '22 at 12:37

0 Answers0