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 не упоминает и не изменяет это при указании "свободной" модели потоков.

Было бы неплохо узнать, кто проголосовал за закрытие этого вопроса. Это было совершенно верно.

Другие вопросы по тегам