Ivan  Petrov
Ivan Petrov

Reputation: 155

Access to main dialog variables within thread (MFC)

I have a GUI application with MFC. I'am lauching thread to process some data using AfxBeginThread(). And i've got problem accessing to main dialog in thread:

Through this struct I'am passing main dialog handler and pointer to main dlg object to thread. But at strcpy() line debugger stops and shows pDlg->0x430f0020 {CTabDlg hWnd=???}

typedef struct {
    LPVOID myHandle;
    LPVOID myPointer;
} sParamData;


UINT WorkerThreadProc_type2( LPVOID Param )
{


    UpdInfo info;   
    sParamData *s;

    s = (sParamData*)Param;
    HWND hMainHandle = (HWND) (*s).myHandle;
    CtabDlg* pDlg = (CtabDlg*)(*s).myPointer;

    strcpy(apikey, pDlg->m_sVar);
...
}

I tried both XP and Windows 7 OS. In XP it always crashes, but in Seven it works. This is how i pass the struct to the thread:

sParamData s;
    s.myHandle = (HWND)GetSafeHwnd();
    s.myPointer = (CtabDlg*) this;

    if(CurrTab == 1)
    {
        AfxBeginThread(WorkerThreadProc_type2, &s, THREAD_PRIORITY_NORMAL,0,0,NULL);
        pPage2->GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);

Thank you for your time!

Upvotes: 0

Views: 1090

Answers (1)

marom
marom

Reputation: 5230

If your code is exactly as your real case then here you are declaring a local sParamData and passing its address to thread. This gives a race condition: s can go out of scope before the thread start execution, (or reaches the point where its content is copied).

sParamData s;
s.myHandle = (HWND)GetSafeHwnd();
s.myPointer = (CtabDlg*) this;

if(CurrTab == 1)
{
    AfxBeginThread(WorkerThreadProc_type2, &s, THREAD_PRIORITY_NORMAL,0,0,NULL);
    pPage2->GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);

The simplest workaround is probably allocate s on heap and delete it in thread after its content has been copied.

Like this:

sParamData *s = new sParamData ;
s->myHandle = (HWND)GetSafeHwnd();
s->myPointer = (CtabDlg*) this;

if(CurrTab == 1)
{
    AfxBeginThread(WorkerThreadProc_type2, s, THREAD_PRIORITY_NORMAL,0,0,NULL);
    pPage2->GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);

And then, inside the thread

UINT WorkerThreadProc_type2( LPVOID Param )
{
    UpdInfo info;   
    sParamData *s = (sParamData*)Param;
    HWND hMainHandle = (HWND) s->myHandle;
    CtabDlg* pDlg = (CtabDlg*)s->.myPointer;
    // assuming s will no longer be used you can delete it here
    delete s ;

Upvotes: 3

Related Questions