Проблема с инициализацией COM
От: Melamed Россия  
Дата: 02.11.22 09:34
Оценка:
Здравствуйте.

Как известно, в ОС Windows существует несколько способов инициализации COM системы:
    С помощью функции OleInitialize
    С помощью функции CoInitializeEx

В моей программе планируется использовать перетаскивание файлов с помощью интерфейса IDropTarget и DirectShow. Причем DirectShow будет использоваться в нескольких потоках. Следовательно, COM система должна инициализироваться с помощью функции CoInitializeEx с флагом COINIT_MULTITHREADED. Но когда я инициализирую так COM систему функция RegisterDragDrop возвращает ошибку. Она требует, чтобы COM система инициализировалась с помощью функции OleInitialize. Но она инициализирует COM систему только в том потоке, в котором была вызвана.

Есть ли способ инициализации COM системы для нескольких потоках и чтоб функция RegisterDragDrop не возвращала ошибку?

Заранее благодарен
P/S Проект WINAPI+STL пишется в C++ MSVS 2015
Re: Проблема с инициализацией COM
От: bnk СССР http://unmanagedvisio.com/
Дата: 02.11.22 09:51
Оценка: 1 (1) +1
Здравствуйте, Melamed, Вы писали:

M>Есть ли способ инициализации COM системы для нескольких потоках и чтоб функция RegisterDragDrop не возвращала ошибку?


COM необходимо инициализировать в каждом потоке, который его использует (каждый поток использует его независимо от других).
Если ты работаешь с пользовательским интерфейсом (UI), то общепринятая стратегия — работа с UI (только) из главного потока приложения.
Не очень понятно зачем тебе несколько потоков для drag-n-drop (перетаскивания)

Если ты используешь DirectShow в каком-то другом потоке, ты можешь его инициализировать его там как тебе надо,
это не повлияет на основной поток. То есть, COM инициализируется (и работает) не "для приложения" а "для потока".
Отредактировано 02.11.2022 9:51 bnk . Предыдущая версия .
Re: Проблема с инициализацией COM
От: qaz77  
Дата: 02.11.22 10:07
Оценка: +2
Здравствуйте, Melamed, Вы писали:
M>Есть ли способ инициализации COM системы для нескольких потоках и чтоб функция RegisterDragDrop не возвращала ошибку?

Просто надо вызывать OleInitialize в каждом потоке, где есть цикл обработки сообщений (UI).

У меня есть проект, где в разных потоках создается несколько top level окон.
Каждое обслуживается своим циклом сообщений.
DragDrop между этими окнами работает отлично, вот эти все IDropTarget и т.д.
Re: Проблема с инициализацией COM
От: okman Беларусь https://searchinform.ru/
Дата: 02.11.22 10:11
Оценка:
Здравствуйте, Melamed, Вы писали:

M>...


M>Есть ли способ инициализации COM системы для нескольких потоках и чтоб функция RegisterDragDrop не возвращала ошибку?


Насколько я знаю, DirectShow может работать как в STA, так и в MTA (Single-Threaded Apartment / Multi-Threaded Apartment).
Вот здесь, например, используется CoInitialize(NULL), что равносильно CoInitializeEx с флагом COINIT_APARTMENTTHREADED, но при этом далее ниже
по тексту сказано, что "DirectShow supports the free-threading model, so you can also call CoInitializeEx with the COINIT_MULTITHREADED flag":

How To Play a File
https://learn.microsoft.com/en-us/windows/win32/directshow/how-to-play-a-file

Так что никто не запрещает вызвать OleInitialize, а затем в этом же потоке использовать и Drag-n-drop, и DirectShow
(OleInitialize — это функция, которая инициализирует STA и делает еще кое-что дополнительно).
А в других потоках, например, где только DirectShow, использовать COINIT_MULTITHREADED, как уже ответили выше.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.