我有一个长时间运行的 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
永远不会被调用/阻塞?
取消COMObject
STDMETHODIMP CCancelCOMObject::Cancel(void)
{
_isCancelled = VARIANT_TRUE;
return S_OK;
}
STDMETHODIMP CCancelCOMObject::get_IsCancelled(VARIANT_BOOL* pVal)
{
*pVal = _isCancelled;
return S_OK;
}
示例COMObject
STDMETHODIMP CSampleCOMObject::LongProcess(ICancelCOMObject* cancel)
{
VARIANT_BOOL isCancelled = VARIANT_FALSE;
while(isCancelled == VARIANT_FALSE)
{
Sleep(1000);
cancel->get_IsCancelled(&isCancelled);
}
return S_OK;
}
最佳答案
事实证明我的 COM+ exe 有这个。
#define _ATL_APARTMENT_THREADED
删除它解决了我的问题。
奇怪的是,ATL 简单对象向导在指定“自由”线程模型时没有提及/修改这一点。
很高兴知道谁投票结束了这个问题。这是完全有效的。
关于.net - COM+ 长时间运行的方法导致其他方法阻塞/挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23457206/