#windows #mfc
#Windows #mfc
Вопрос:
Я перехожу с Win7 на Win10 и недавно столкнулся с «Ошибкой неправильного аргумента», открыв файл.
Ошибка возникает очень редко и случайным образом.
Дополнительная информация или информация о стеке вызовов не предоставляются. Мне пришлось выполнять глубокий поиск в коде MFC. DocManager открывает документ, а затем вызывает CDocument::SetPathName(..,TRUE)
, чтобы добавить текущий файл в список последних файлов.
Кажется, эта функция теперь использует функцию OLE / COM.
void CRecentFileList::Add(LPCTSTR lpszPathName, LPCTSTR lpszAppID)
{
:
:
Add(lpszPathName);
HRESULT hr = S_OK;
CComPtr<IShellItem> psi = NULL;
hr = _AfxSHCreateItemFromParsingName(lpszPathName, NULL, IID_IShellItem, reinterpret_cast<void**>(amp;psi));
ENSURE(SUCCEEDED(hr)); // Remark Tom: This throws an AfxInvalidException()
}
код ошибки hr -2147221008, что означает CoInitialize
, что он не был вызван.
Я удивлен, потому что я никогда не использовал COM / OLE.
Преодолейте эту ошибку, я должен добавить AfxOleInit()
InitInstance
.
Мой вопрос в том, как мне заранее узнать, нужно ли моему приложению использовать OLE / COM?
Дополнительный вопрос, есть ли у меня какие-либо недостатки, если я использую COM / OLE в своем приложении. (память и скорость)?
Комментарии:
1. Учитывая, что большая часть поверхности API Windows доступна через COM, справедливо предположить, что любое нетривиальное приложение Windows в какой-то момент будет использовать COM. Инициализация потока в COM-квартире не бесплатна. После выполнения нет никаких накладных расходов во время выполнения. Маловероятно, что регистрация потоков для COM приведет к заметному снижению производительности. Обратите внимание, что COM инициализируется для каждого потока. Один вызов инициализации
InitInstance
только зарегистрирует ваш поток пользовательского интерфейса.2. PS: Ваше приложение MFC, вероятно, всегда использовало COM, но не выходило из строя, хотя должно было (см. Почему работает CoCreateInstance, хотя мой поток никогда не вызывал CoInitialize? Проклятие неявного MTA для деталей). Возможно, что-то изменилось в Windows 10.
Ответ №1:
Мой вопрос в том, как мне заранее узнать, нужно ли моему приложению использовать OLE / COM?
Предполагается, что приложения MFC всегда инициализируют OLE / COM, в частности, с помощью модели параллелизма STA (single thread apartment). Это делается автоматически в шаблонах, созданных мастером, в противном случае это должно быть сделано явно в коде пользователя. Из документации CWinApp:
Приложения MFC должны быть инициализированы как однопоточная квартира (STA).
Если вы вызываете CoInitializeEx в переопределении InitInstance, укажите COINIT_APARTMENTTHREADED (а не COINIT_MULTITHREADED).
Наличие OLE / COM, всегда инициализируемого STA, также позволяет избежать проклятия неявного MTA, упомянутого @IInspectable в комментарии.