在 VS2013 MFC 專案中,繼承 CWinThread 封裝大漠插件 (dm.dmsoft) 向多個目標窗口發送字符串。現象:創建兩個線程對象分別綁定不同窗口,但只有最後創建的線程能發送成功,切換窗口焦點後另一個失效。這是典型的 **COM STA (單線程單元) 模型導致的跨線程調用封送失敗**。
ThreadingModel = Apartment)。CWinThread 線程調用 CoInitialize(NULL) 初始化獨立的 STA。Cdmsoft 對象,線程 B 無法直接調用其方法(SendString 等),需經過接口封送。CWinThread 未自動建立代理/存根進行跨 STA 封送,導致調用失效或崩潰。Cdmsoft 實例。PostMessage/SendMessage 將任務參數(目標句柄、字符串)發送給主線程。dm.SendString(hwnd, str)。ThreadingModel = Free (MTA) 或 Both,可在任意線程直接調用。// 線程函數內
::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); // 明確 STA
Cdmsoft dm;
dm.CreateDispatch(_T("dm.dmsoft")); // 當前線程創建自己的實例
dm.BindWindow(hwnd, ...);
dm.SendString(hwnd, str); // 同線程調用,合法
::CoUninitialize();
// 主對話框/視圖類成員
std::map m_dmMap; // 主線程持有所有實例
// 或陣列 Cdmsoft m_dm[2];
// 工作線程發送任務
::PostMessage(m_hMainWnd, WM_USER_SEND_STRING, (WPARAM)hwnd, (LPARAM)new CString(str));
// 主線程消息處理
LRESULT CMainDlg::OnSendString(WPARAM wParam, LPARAM lParam) {
HWND hwnd = (HWND)wParam;
CString* pStr = (CString*)lParam;
auto it = m_dmMap.find(hwnd);
if (it != m_dmMap.end()) {
it->second.SendString(hwnd, *pStr);
}
delete pStr;
return 0;
}
IGlobalInterfaceTable、代理/存根)。