哪些是从线程通过 PostMessage 发送 CString 的安全方法

fla*_*iu2 5 c++ mfc multithreading thread-safety visual-c++

从线程发送CString通过的安全/最佳方式PostMessage是什么?要CString在堆上创建并在接收者收到此信息时进行清理CString

解决方案1:在线程中:

CString* pError = new CString(_T("Unknown error"));
::PostMessage(...(LPARAM)pError);
Run Code Online (Sandbox Code Playgroud)

在主线程中,在 GUI 的某个地方:

CString* pError = (CString*)lParam;
GetDocument()->DoSomething(*pError);
delete pError;
Run Code Online (Sandbox Code Playgroud)

解决方案 2: 或者,将CString对象保留为CThread类内部的成员变量?

class CPlanThread : public CThread [: public CObject]
{
public:
DECLARE_DYNAMIC(CPlanThread)

...
protected:
CString* m_pMessage;

};
Run Code Online (Sandbox Code Playgroud)

CPlanThread::CPlanThread()
:m_pMessage(NULL)
{
m_pMessage = new CString(_T(""));
}

CPlanThread::~CPlanThread()
{
if(NULL != m_pMessage)
    delete m_pMessage;
}
Run Code Online (Sandbox Code Playgroud)

和线程中的某个地方:

::PostMessage(m_hWndMain, WMU_NOTIFYTHREAD, 0, (LPARAM)m_pMessage);
Run Code Online (Sandbox Code Playgroud)

在主线程中,在 GUI 的某个地方:

CString* pError = (CString*)lParam;
GetDocument()->DoSomething(*pError);
Run Code Online (Sandbox Code Playgroud)

以上两种解决方案都安全吗?感谢您的任何解释。

IIn*_*ble 3

第一个选择是更安全的选择。*这可能导致资源泄漏的唯一原因是,如果调用::PostMessage失败,并且您没有在发送方中进行清理。请注意,这不会导致崩溃。

第二种选择会产生竞争条件,因为您持有一个指针,而您打算转移其所有权。如果 GUI 线程在线程对象被销毁后尝试访问该字符串,则您正在访问随机内存。如果幸运的话,这可能会导致立即崩溃。

根据您的具体用例,您可能需要考虑使用第三种替代方案:使用CString具有自动存储持续时间和通过消息发送进行线程同步的对象,例如:

CStringW err( L"Unknown error" );
::SendMessage( ..., (LPARAM)&err );
Run Code Online (Sandbox Code Playgroud)

只要字符串对象位于其消息处理程序中,接收线程就可以使用该字符串对象,并且发送者将自动清理资源。


* 假设两个线程都在同一个模块中实现。请务必阅读跨 DLL 边界传递 CRT 对象的潜在错误,以防万一。