Search code examples
multithreadingc++-cli

C++/CLI - Update a custom control from a parent form "for loop" does not work


Rewriting the question with more clarity.

I have a WinForm that consists of a UserControl called ProgressTracker that shows the user a status message and completion % using labels in a TableLayoutPanel. The progress update usually comes from events getting fired in the MainForm that further call their respective methods. I was testing the ProgressTracker today by the following methods.

ProgressTracker^ pt; //Gets allocated when InitializeComponent() is called as it is added using the designer.

System::Void MainForm::Process()
{
    pt->TaskComplete = false;

    pt->CurrentStage = 0;
    pt->MaximumStage = 15;
    pt->Percentage = 0;

    for (int i = 0; i < 15; i++)
    {
        pt->CurrentStage = i; //integer property in ProgressTracker that further calls label->Text property.
        pt->Percentage = i;  //integer property in ProgressTracker that further calls label->Text property.
        pt->StatusMessage  //integer property in ProgressTracker that further calls label->Text property.
        System::Threading::Thread::Sleep(300);
    }

    pt->TaskComplete = true;
}
System::Void MainForm::ButtonClick(some arguments)
{
      System::Threading::Thread^ thr = gcnew System::Threading::Thread
      (gcnew System::Threading::ThreadStart(this, &MainForm::Process));
      thr->IsBackground = true;
      thr->Start();

      while (true) {} //Test 1
    //while (true) { if (pt->TaskComplete) break; } //Test 2
 }

I do not want the MainForm::ButtonClick method to finish until the MainForm::Process has finished. That is why I put an inifinite loop at the end there. But no matter what I do, the GUI does not update until MainForm::ButtonClick returns.

I have read a lot of posts on Stack about using BGWorker or using BG thread. But as you can see, I have already called a thread in the background but the GUI does not change until the MainForm::ButtonClick ends. And I cannot let MainForm::ButtonClick to end until MainForm::Process has finished due to some reason that is irrelevant to this post.

Is there a way for me to UPDATE the labels of ProgressTracker from MainForm events without having the event methods to end first?

Edit - Whether the GUI updates or not is my secondary concern. What I am trying to actually understand here is why is it that the GUI does not update until MainForm::ButtonClick returns despite MainForm::Process being called from a BG thread.


Solution

  • The problem: GUI does not update until event method returns.

    Suggestions: I have been suggested Background workers and threads.

    So, none of the suggestions work because the readers appear to not understand the problem correctly. THE GUI DOES NOT UPDATE UNTIL THE EVENT METHOD MainForm::ButtonClick RETURNS. Emphasis on the "UNTIL THE EVENT METHOD MainForm::ButtonClick RETURNS" part. I have tried BG workers and threads but no matter what I do, the GUI will not update until the MainForm::ButtonClick method has finished execution.

    What is the problem? I do not care if the GUI updates or not. What I need answers for is why is it that the GUI does not update until MainForm::ButtonClick returns despite MainForm::Process being called from a BG thread.

    Current Solution: from MainForm::ButtonClick, call the MainForm::Process in a BG Worker or thread and then let MainForm::Process raise a separate even upon its completion.