COM +长时间运行的方法导致其他方法阻塞/挂起

时间:2014-05-04 14:10:32

标签: .net multithreading com apartments

我有一个长时间运行的COM +方法,我需要能够从另一个线程取消。我正在使用C#/ .NET来交互COM +对象。我配置了两个COM +对象以获得" Free"线程模型。这个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完成。我不知道为什么这样做,因为我认为" Free"线程模型允许实现管理同步。

这是一个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 个答案:

答案 0 :(得分:3)

事实证明我的COM + exe有这个。

#define _ATL_APARTMENT_THREADED

删除它解决了我的问题。

在指定“Free”线程模型时,ATL简单对象向导没有提及/修改它,这很奇怪。

知道谁投票结束这个问题会很高兴。这完全有效。