Короче говоря: в приложении C #, которое работает с COM inproc-сервером (dll), я сталкиваюсь с исключением "0x80010100: системный вызов не выполнен", а в режиме отладки также исключение ContextSwitchDeadlock.
Теперь подробнее:
1) Приложение C # инициализирует STA, создает COM-объект (зарегистрированный как «Квартира»); затем подписывается на свою точку подключения и начинает работать с объектом.
2) На некотором этапе COM-объект генерирует множество событий, передавая в качестве аргумента очень большую коллекцию COM-объектов, которые создаются в одной квартире.
3) Обработчик событий на стороне C # обрабатывает вышеуказанную коллекцию, иногда вызывая некоторые методы объектов. На некотором этапе последние вызовы начинают терпеть неудачу с вышеуказанными исключениями.
На стороне COM квартира использует скрытое окно, чей winproc выглядит так:
typedef std::function<void(void)> Functor;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case AM_FUNCTOR:
{
Functor *f = reinterpret_cast<Functor *>(lParam);
(*f)();
delete f;
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
События публикуются в этом окне из других частей COM-сервера:
void post(const Functor &func)
{
Functor *f = new Functor(func);
PostMessage(hWind_, AM_FUNCTOR, 0, reinterpret_cast<LPARAM>(f));
}
События - это стандартные реализации ATL CP, связанные с фактическими параметрами, и они сводятся к чему-то вроде этого:
pConnection->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, ¶ms, &varResult, NULL, NULL);
В C # обработчик выглядит так:
private void onEvent(IMyCollection objs)
{
int len = objs.Count; // usually 10000 - 25000
foreach (IMyObj obj in objs)
{
// some of the following calls fail with 0x80010100
int id = obj.id;
string name = obj.name;
// etc...
}
}
==================
Итак, может ли описанная выше проблема возникнуть только потому, что очередь сообщений в квартире слишком загружена событиями, которые она пытается доставить? Или цикл сообщений должен быть полностью заблокирован, чтобы вызвать такое поведение?
Предположим, что в очереди сообщений есть 2 последовательных события, которые оцениваются как вызов onEvent. Первый вводит управляемый код C #, который пытается повторно ввести неуправляемый код той же квартиры. Обычно это разрешено, и мы делаем это много. Когда, при каких обстоятельствах он может потерпеть неудачу?
Спасибо.