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.

  1. Store it in a class member variable.
  2. 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)
{
   ...
}