After spending a bit of time with simple UWP applications with C++/CX and ++/WinRT I have begun to enjoy some of the features of targeting that environment for Windows UI app development.
Now having to go back to a more familiar MFC application development I want to change my approach to something that is similar to UWP app development. The idea is to use asynchronous C++11 threads to generate content and modify content that is displayed in the MFC UI.
The main change I want to make is to use C++11 threads to off load some time consuming tasks and have those threads communicate the results back to the main MFC UI.
Some of the tasks that I am looking to off load onto C++11 threads, which are similar to what I would use with asynchronous tasks with C++/CX and C++/WinRT in UWP apps are:
- connect to and exchange data with another computer
- open a data file and parse through it to update the UI view
- convert a data file to another format such as CSV and export to a file
- read a file in a format such as CSV and convert the content into a data file
- perform searches and filtering of the presentation of the data file in the UI
The problem I am running into is similar to the problem described in Can I have multiple GUI threads in MFC? however I am looking for a general approach rather than the specific progress bar update in that question.
I have been trying a simple test with an experimental MFC app using the Visual Studio template which has a tree control docked on the left to build the tree in a worker thread.
If I have a CViewTree
, an MFC window that displays a tree view, which I want to update from a C++11 thread, I am currently using ::PostMessage()
to request that the tree control in the docked pane is updated.
If I use a lambda with a global std::thread
such as the following code:
std::thread t1;
void CClassView::FillClassView()
{
// ::SendMessage() seems to deadlock so ::PostMessage() is required.
t1 = std::thread([this]() { Sleep(5000); ::PostMessage(this->m_hWnd, WM_COMMAND, ID_NEW_FOLDER, 0); });
}
the message handler for the MFC docked pane which looks like:
void CClassView::OnNewFolder()
{
t1.join(); // this join seems to deadlock if ::SendMessage() is used.
AddItemsToPane(m_wndClassView);
}
does indeed update the MFC docked pane with the tree control content just as if the function AddItemsToPane(m_wndClassView);
were called at the same place where the C++11 thread is created. The pane update is delayed by 5 seconds when the C++11 thread is used just to provide a visible indication that the thread approach is actually working.
My problem is that I want the C++11 thread to create the content for the tree control and provide it to the docked pane rather than having the docked pane generate the content.
Thus far the only approach I can think of is to develop my own class library that will provide C++11 thread analogues to the MFC library and controls using ::PostMessage()
to send the appropriate Windows messages to the designated MFC window or control.
I am wondering if it is possible to have the C++11 threads have their own, shadowing MFC control which they update and then send a message to the UI asking the UI to update its displayed control with the contents of the shadow MFC control? Or is there some other approach that people are using?
I am looking for some other, less arduous approaches to solving this problem of updating an MFC UI from C++11 threads.
By the way #1 ::SendMessage()
appears to deadlock on the join()
in CClassView::OnNewFolder()
which I assume means that some kind of synchronization between the C+11 thread and the UI thread is blocking the C++11 thread from reaching it's side of the join()
?
By the way #2 It would also seem that using the actual Window handle rather than the this
pointer in the lambda for the C++11 thread would be safer. Just in case the this
pointer becomes undefined for some reason such as the control is removed?
Aucun commentaire:
Enregistrer un commentaire