0

I am making a simulation tool, that runs simulation (in a separate thread) over user defined number of iterations, which can be entered in an Edit control on the Ribbon Bar. I would like to reuse it to show current iteration during simulation. I also also put CMFCRibbonProgressBar to show the progress. The Ribbon Bar is created with resource editor.

The question is what is the what to get the progress bar and iteration counter to get timely updated without causing the GUI to become unresponsive?

The conventional way over ON_UPDATE_COMMAND_UI routines requires activity in the window, like moving the mouse.

So I probably need a thread that would update this controls. Things like simply creating a thread and trying to update the controls from or using concurrency::parallel_invoke are not suitable.The former simply doesn't work, the latter works, but causes GUI to freeze.

I store pointers in my document to simplify access to the controls. https://stackoverflow.com/a/25429446?noredirect=1

My general idea is (pseudocode)

beginUpdatingThread()
{
while(simulating)
{
updateEditControl();
updateProgressBar();
sleep_40_ms();//conserves the resorces as there is no sense to update more frequent than 25 times per second
}
}

What is correct way of implementing this?

Community
  • 1
  • 1
Andrey Pro
  • 501
  • 1
  • 10
  • 22

2 Answers2

0
ASSERT(m_hWnd!=NULL);

MSG msg;

while (simulating)
{
  // Handle dialog messages
  while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  {
    if(!IsDialogMessage(&msg))
    {
      TranslateMessage(&msg);
      DispatchMessage(&msg);  
    }
  }
}
thomiel
  • 2,467
  • 22
  • 37
  • Could you please add some clarification to this code? How it solves the OPs issue and what it does? – Ilya Luzyanin Aug 31 '14 at 14:59
  • The code just keeps your GUI from freezing as it allows your dialog messages to be processed while your simulation is running. It's pretty much straight forward, I thought. If this doesn't solve your problem, maybe you could provide real MFC code tather than pseudocode, so I can better understand what you mean. – thomiel Aug 31 '14 at 15:42
0

I solved this by adding a method to the main window that performs the update. now the thread updating from above continually post messages to the main window to perform the update:

auto h = static_cast<CMainFrame*>(AfxGetMainWnd())->m_hWnd;
    //here code for starting simulation in a separate thread

    std::thread updating([this,h]{

        while (simulating)
        { 
            ::PostMessage(h, WM_UPDATE_VISUALS, sumulator.getCurrentIteration(), 0);

        std::this_thread::sleep_for(std::chrono::milliseconds(40));
        }
        ::PostMessage(h, WM_UPDATE_VISUALS, num_iterations, 0);
    });
updating.detach()

I made a subtle mistake at first by capturing h by reference, which quickly expires But in the end, the above code does exactly what I wanted to achieve

Andrey Pro
  • 501
  • 1
  • 10
  • 22