COM+ длительный метод, вызывающий блокирование / зависание других методов
У меня есть длительный метод COM+, который я должен иметь возможность отменить из другого потока. Я использую C#/.NET для взаимодействия объектов COM+. Я настроил оба объекта COM+ для создания "свободной" модели потоков. Этот пример C# демонстрирует, как я собираюсь использовать объекты COM+.
static void Main(string[] args)
{
var sampleCOMClass = new SampleCOMObjectClass();
var cancelToken = new CancelCOMObjectClass();
try
{
Task.Factory.StartNew(() =>
{
Thread.Sleep(TimeSpan.FromSeconds(10));
cancelToken.Cancel(); // this method never makes it to COM
Console.WriteLine("Cancelled!");
});
sampleCOMClass.LongProcess(cancelToken);
}
finally
{
Marshal.ReleaseComObject(sampleCOMClass);
Marshal.ReleaseComObject(cancelToken);
}
}
Мой длительный процесс правильно проверяет токен отмены, чтобы определить, должны ли мы закончить обработку, но Cancel
метод никогда не доходит до объектов COM+. Это как если бы метод блокировал, ожидая LongProcess
заканчивать. Я не знаю, почему это происходит, потому что я думал, что "свободная" модель потоков позволила реализациям управлять синхронизацией.
Вот репозиторий BitBucket с минимальным примером для воспроизведения. https://bitbucket.org/theonlylawislove/so-blocking-com-call
Почему Cancel
никогда не звонят / блокируют?
CancelCOMObject
STDMETHODIMP CCancelCOMObject::Cancel(void)
{
_isCancelled = VARIANT_TRUE;
return S_OK;
}
STDMETHODIMP CCancelCOMObject::get_IsCancelled(VARIANT_BOOL* pVal)
{
*pVal = _isCancelled;
return S_OK;
}
SampleCOMObject
STDMETHODIMP CSampleCOMObject::LongProcess(ICancelCOMObject* cancel)
{
VARIANT_BOOL isCancelled = VARIANT_FALSE;
while(isCancelled == VARIANT_FALSE)
{
Sleep(1000);
cancel->get_IsCancelled(&isCancelled);
}
return S_OK;
}
1 ответ
Оказывается, у моего COM+ exe было это.
#define _ATL_APARTMENT_THREADED
Удаление этого решило мою проблему.
Странно, что мастер простых объектов ATL не упоминает и не изменяет это при указании "свободной" модели потоков.
Было бы неплохо узнать, кто проголосовал за закрытие этого вопроса. Это было совершенно верно.