2011-08-25 35 views
1

从工作线程访问MFC控件的最佳方式是什么?如何从工作线程访问MFC控件?

什么是访问控件的MFC习惯用法?

我读到这里http://www.flounder.com/workerthreads.htm下面的办法,但我不很喜欢的CStringnew,我怎么可以肯定的CString会妥善deleted

typedef struct tagTP 
{ 
    HWND hwnd; 
    int n; 
} TP; 

BEGIN_MESSAGE_MAP(CMyDlg, CDialog) 
    // ... 
    ON_MESSAGE(UWM_UPDATE_RESULTS, OnUpdateResults) 
END_MESSAGE_MAP() 

void CMyDlg::OnBnClickedDoWork() 
{ 
    TP* tp = new TP; 
    tp->hwnd = m_hWnd; 
    tp->n = 42; 

    AfxBeginThread(doWork, tp); 
} 

UINT CMyDlg::doWork(LPVOID p) 
{ 
    TP* tp = reinterpret_cast< TP* >(p); 
    CWnd* dlg = FromHandle(tp->hwnd); 

    if (tp->n == 42) { 
     CString* s = new CString("Is the Answer to the Ultimate Question of Life, the Universe, and Everything"); 
     dlg->PostMessage(UWM_UPDATE_STATUS, 0, reinterpret_cast<LPARAM>(s)); 
    } 

    return 0; 
} 

LRESULT CMyDlg::OnUpdateResults(WPARAM,LPARAM lParam) 
{ 
    CString* s = reinterpret_cast<CString *>(lParam); 
    m_result.AddString(*s);// m_result is a CListBox 
    delete s; 
    UpdateData(FALSE); 
    return 0; 
} 
+1

您应该将CString指针存储在OnUpdateResults()中的智能指针中,以确保在处理过程中出现异常时它会被销毁。 – tinman

回答

0

使用PostMessage(..)是正确的。考虑使用SendMessage(..) - 哪个阻塞直到完成。 传递指向新对象的指针很常见 - 检查PostMessage(..)的返回值以检查它是否已发布。

我该如何确定CString将被正确删除?

如前所述,检查PostMessage(..)的返回值并在退出消息循环时处理整个消息队列。

0

作为一般规则,MFC控件只能从创建它们的线程访问。这就是为什么您找到的样本需要通过传递消息的额外步骤。该消息由创建该控件的线程接收并处理。

CString在OnUpdateResults()中正确删除。

0

除了@ Simon的回答,如果你有更复杂的情况,很难找出谁应该删除CString(或任何类型),请考虑std :: tr1 :: shared_ptr。它会照顾删除。

+1

您可以在发布(然后释放指针)之前以及在消息处理程序中接收它之后(使用智能指针进行分配)完成此操作。这只是关于异常安全。您不能直接发布智能指针。 – Simon

+0

在这种情况下'shared_ptr'会做什么?它是一个C++对象,不能以'sizeof(void *)'字节传递。它必须分配然后释放。根本没有帮助。 – Ajay

+0

@dgnorton谢谢,我不熟悉shared_ptr,我该如何使用它? –