У меня есть приложение MFC, использующее библиотеку параллельных шаблонов для некоторых асинхронных задач. Некоторые из них используют COM-объекты, поэтому мне нужно инициализировать библиотеку COM в таких задачах. Во всех таких случаях я использую инициализацию модели COM STA, потому что основной поток - приложение MFC (поток приложений MFC может быть только STA), и я не знаю, в каком контексте протектора будут вызваны мои задачи.COM STA модель в Parallel Patterns Library (PPL)?
Некоторые примеры:
BOOL CMyApp::InitInstance() {
// base initialization
CWinAppEx::InitInstance();
AfxOleInit();
// ... some code ...
// PPL usage
{
Concurrency::task_group aTasks;
// Task1
aTasks.run([&](){
HRESULT hRes = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(hRes)) {
Sleep(100);
::CoUninitialize();
}
});
// Task2
aTasks.run([&](){
HRESULT hRes = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(hRes)) {
Sleep(100);
::CoUninitialize();
}
});
// Task3
aTasks.run([&](){
HRESULT hRes = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(hRes)) {
Sleep(100);
::CoUninitialize();
}
});
aTasks.wait();
}
}
Этот код работает нормально на Windows 7/XP. Но в Windows 8.1 с C++ 2012 Platform Toolset задачи 1 и 2 не работают, потому что CoInitializeEx() возвращает ошибку RPC_E_CHANGED_MODE! Задача 3 обычно называется ядром PPL в основном контексте потока MFC, который является OLE, а его COM уже инициализирован как COINIT_APARTMENTTHREADED, поэтому CoInitializeEx() возвращает код успеха S_FALSE (двойная инициализация).
Для задач 2 и 3 ядро PPL создает отдельные потоки, которые не являются PRE-инициализированными как COM в Windows 7/XP, поэтому задачи firts line инициализируют COM с успехом. BUT on Windows 8.1 все выглядят как потоки PRE-INITIALIZED, поскольку COM с флагом COINIT_MULTITHREADED и последующим вызовом CoInitializeEx (..., COINIT_APARTMENTTHREADED) возвращает ERROR!
Какого черта! Как я могу определить правильное правило инициализации COM в окне 8.1? Где моя ошибка? PPL не гарантируется моим контекстом потока для задач, и это может быть основной поток, который в MFC ДОЛЖЕН быть STA. И я не могу определить, когда я должен использовать инициализацию MTA или STA COM.
Пожалуйста, помогите мне. Может быть, это ошибка в коде ядра PPL из набора инструментов платформы C++ 2012 года или ошибки в использовании PPL с Windows 8.1?
Мда, жесткие печенье. Вы можете увидеть его в функции VC \ crt \ src \ InternalContextBase.cpp, InternalContextBase :: Dispatch(). Обратите внимание на вызов WinRT :: RoInitialize (RO_INIT_MULTITHREADED); Не случайно. Требование к потоку STA для жестких требований заключается в том, что он должен перекачать контур сообщения. Задачи этого не делают. –
Какой смысл инициализировать WinRT в настольных приложениях? – 23W