Can't save CDocument in a worker thread -- object is destroyed from memory before thread starts
This is the issue of the scope of variable.
Following comments specified the scope of local variable threadInput
.
ProcessDocumentThreadInput threadInput(this, lpszPathName); // <=== threadInput created
if (m_bTempMode)
{
m_TempSaveThread = AfxBeginThread(SaveDocumentThread, &threadInput);
// This fixes the problem, but is considered unstable
// if (m_TempSaveThread->m_hThread)
// WaitForSingleObject(m_TempSaveThread->m_hThread, 500);
return TRUE; // <=== threadInput destructed
}
Your workaround WaitForSingleObject()
delays the destruction of the variable threadInput
and you see the result.
To overcome the scope of local variable.
- Store it in a class member variable.
- Store it as a (better be smart) pointer and (better not to) handle it's destruction.
Edit:
As @Jabberwocky stated, function OnSaveDocument()
might be called more than twice since it's called by background thread.
I'll suggest to refactor the save()
function out and let if
and else
to call them seperately.
As others have pointed out, the problem is the lifetime of threadInput
ends before the thread begins.
You can dynamically allocate the instance of ProcessDocumentThreadInput
and pass the pointer to that instance to the thread.
auto* threadInput = new ProcessDocumentThreadInput(this, lpszPathName);
...
AfxBeginThread(SaveDocumentThread, threadInput);
However, in this case, the responsibility to release the memory gets messy.
Since you put C++11 tag in your question, you might want to make use of std::shared_ptr
or std::unique_ptr
and pass it to the thread, which would land you in using std::thread
instead of AfxBeginThread. (BTW, I have no experience using MFC.)
BOOL SPackagerDoc::OnSaveDocument( IN LPCTSTR lpszPathName)
{
...
std::thread t(SaveDocumentThread, std::make_unique<ProcessDocumentThreadInput>(this, lpszPathName));
...
}
...
StUInt32 SaveDocumentThread(std::unique_ptr<ProcessDocumentThreadInput>&& threadInput)
{
...
}