У меня есть приложение MFC, которое использует библиотеку параллельных шаблонов для некоторых асинхронных задач. Некоторые из них используют COM-объекты, поэтому мне нужно инициализировать COM-библиотеку в таких задачах. Во всех таких случаях я использую инициализацию модели COM STA, потому что основным потоком является приложение MFC (поток приложения MFC может быть ТОЛЬКО STA), и я не знаю, в каком контексте протектора будут вызываться мои задачи.
Пример:
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 создает отдельные потоки, которые предварительно не инициализируются как COM в Windows 7 / XP, поэтому первая строка задач успешно инициализирует COM. НО в Windows 8.1 все выглядит так, как будто потоки ПРЕДНАЗНАЧЕНЫ как COM с флагом COINIT_MULTITHREADED, а последующий вызов CoInitializeEx (..., COINIT_APARTMENTTHREADED) возвращает ОШИБКУ!
Какого черта! Как я могу определить правильное правило инициализации COM в Window 8.1? В чем моя ошибка? PPL не гарантируется для моего контекста потока для задач, и это может быть основной поток, который в MFC ДОЛЖЕН быть STA. И я не могу определить, когда мне следует использовать инициализацию MTA или STA COM.
Пожалуйста помогите. Может быть, это ошибка в основном коде PPL из набора инструментов платформы C ++ 2012 или ошибка в использовании PPL с Windows 8.1?