如何从工作线程访问 MFC 控件?

Posted

技术标签:

【中文标题】如何从工作线程访问 MFC 控件?【英文标题】:How to access an MFC control from a worker thread? 【发布时间】:2011-08-25 12:10:48 【问题描述】:

从工作线程访问 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;

【问题讨论】:

您应该将 CString 指针存储在 OnUpdateResults() 中的智能指针中,以确保在处理过程中出现异常时将其销毁。 【参考方案1】:

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

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

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

【讨论】:

【参考方案2】:

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

在 OnUpdateResults() 中正确删除了 CString。

【讨论】:

【参考方案3】:

除了@Simon 的回答之外,如果您有一个更复杂的场景,即很难确定谁应该删除 CString(或任何类型),请考虑 std::tr1::shared_ptr。它将负责删除。

【讨论】:

您可以在发布之前(然后释放指针)和在消息处理程序中接收它之后(使用智能指针分配它)执行此操作。这只是关于异常安全。您不能直接发布智能指针。 shared_ptr 在这种情况下会做什么?它是一个 C++ 对象,不能仅以 sizeof(void*) 字节传递。它必须被分配然后释放。一点用都没有。 @dgnorton 谢谢,我对shared_ptr不熟悉,怎么用?

以上是关于如何从工作线程访问 MFC 控件?的主要内容,如果未能解决你的问题,请参考以下文章

c ++ MFC从工作线程设置/附加文本到richedit控件

MFC:在工作线程中使用对象的成员函数时出现访问冲突错误

从 MFC 中的工作线程调用 Beginwaitcursor 函数

如何修复错误:从不同的线程访问了“dataGridView1”控件[重复]

MFC - 获取特定窗口的设备上下文

[转]MFC子线程中更新控件内容的两种办法