CoInitialize Вызывается из BackgroundWorker C #

У меня есть приложение C # Windows Form, которое использует C ++ DLL. Внутри DLL я инициализирую COM:

auto hResult = CoInitialize(NULL); // Initialize COM
if (hResult != S_OK && hResult != S_FALSE) {
WSACleanup();
return 1;
}

Когда я запускаю DLL вне процесса BackgroundWorker, все работает нормально. Однако, если я это сделаю, мое приложение зависнет, когда DLL будет завершена. Итак, я пытаюсь использовать BackgroundWorker; но всякий раз, когда я запускаю DLL внутри функции DoWork, я не могу инициализировать COM.

Может кто-нибудь объяснить это, пожалуйста, и предложить какие-либо предложения о том, как запустить мою DLL в BackgroundWorker?

Спасибо.

0

Решение

BackgroundWorker использует потоки пула потоков. Потоки потоков .NET автоматически инициализируются в MTA (CoInitializeEx(NULL, COINIT_MULTITHREADED)). Ваша DLL пытается инициализировать поток в STA (CoInitialize()), и этот звонок должен возвращаться RPC_E_CHANGED_MODE, Это провал.

Как правило, я бы не инициализировал COM в вызывающей ветке из библиотеки. Я бы посчитал это антипаттерном. Несколько клиентских приложений могут использовать несколько библиотек, и каждая из этих библиотек может (попытаться) инициализировать COM. Лучшим вариантом было бы, чтобы владелец каждого потока инициализировал COM в этом потоке. Ваше клиентское приложение будет инициализировать COM для основного потока и любых фоновых потоков, которыми он владеет (.NET сделает все это за вас). Каждая библиотека будет указывать (в документации) требования к потокам / апартаментам для своих точек входа (например, «Эта DLL FooExport Функция должна вызываться из потока STA. «). Потоки, принадлежащие библиотеке, будут иметь состояние квартиры, контролируемое библиотекой. Единственное реальное преимущество для вызова CoInitialize/Ex внутри библиотеки нужно попытаться определить состояние квартиры, в которой находится ваш поток, чтобы программные требования к квартире были проверены программно, но есть некоторые сценарии (квартиры с нейтральной резьбой), в которых это становится проблематичным.

По вашему сценарию:

  • Если вашей DLL требуется STA, создайте фоновый поток вручную в клиентском приложении и установите состояние квартиры на STA перед запуском потока (см. SetApartmentState). Также рассмотрите возможность удаления CoInitialize позвони в свою библиотеку.
  • Если ваша DLL может использовать MTA, либо удалите CoInitialize позвоните из вашей DLL или используйте CoInitializeEx(NULL, COINIT_MULTITHREADED),
1

Другие решения

Других решений пока нет …