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

标签 .net multithreading com apartments

我有一个长时间运行的 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/

相关文章:

c# - File.ReadAllLines 或 Stream Reader

c# - 来自外部进程的 C# 中的线程问题

PHP 使用 COM 将 word 转换为 html

.net 应用程序无法连接到 DB2 数据库

c# - 为什么哈希表和字典不使用 Equals() 方法而不是 GetHashCode 在 .NET 中进行键比较?

在 main 中调用一次时,Python 线程运行两次

java - Log4j 异步附加器的使用?

C# 异步等待和线程池

c++ - 有人可以解释 c++ FAILED 函数吗?

c# - 在非托管 C++ 项目中使用 C# COM -> 0x7697C41F (KernelBase.dll) 处的第一次异常