我有一个长时间运行的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;
}
答案 0 :(得分:3)
事实证明我的COM + exe有这个。
#define _ATL_APARTMENT_THREADED
删除它解决了我的问题。
在指定“Free”线程模型时,ATL简单对象向导没有提及/修改它,这很奇怪。
知道谁投票结束这个问题会很高兴。这完全有效。