c# - COM 和线程安全

标签 c# com thread-safety locking

我需要将 ASP.NET MVC 网站与第 3 方 COM 应用程序集成。代码看起来像这样:

Type type = Type.GetTypeFromProgID(progID);
dynamic obj = Activator.CreateInstance(type);
if (!obj.DBOpenedStatus)
{
    obj.InitApplicationContext();
    //do stuff with other COM objects
}

问题是一段时间后我开始收到 COMExceptions 很可能是因为我从未使用 obj.ReleaseApplicationContext() 关闭该上下文。所以我正在考虑编写一个实现 IDisposable 的包装器,以便我可以在构造函数中初始化上下文并在它被释放时释放它。但是我需要一个 lock 以便在当前线程仍在工作时另一个线程不会关闭上下文。代码如下所示:

lock (_locker)
{
    using (MyComContextWrapper comContext = new MyComContextWrapper())
    {
        //do stuff with other COM objects
    }
}

我对线程安全知之甚少,所以我想问你以下问题:

  1. 我的方法有什么问题吗?
  2. 还有什么我应该考虑的(比如死锁或其他什么)吗?
  3. 您会推荐一种不同的方法吗?

编辑 1:
我在注册表中查找了 COM 类的 progID,发现 ThreadingModel=Apartment 因此 COM 应用程序使用了 Single-Threaded Apartment 类型。

编辑 2:
COM 应用程序使用一个系统为对象生成 ID,以便当这些对象在数据库中持久化时,它们已经具有一个 ID。该系统涉及在注册表中写入一些信息。过了一会儿,这个系统出了问题,我开始收到 violation of primary key constraint 错误。

编辑 3:
我有时会收到 System.ArgumentNullException: Value cannot be null。参数名称:类型为 Activator.CreateInstance(Type type)。这可能是因为我正在尝试从另一个线程创建一个新的 STA 对象吗?

编辑 4:
有人要求我发布完整的 COMExceptions 堆栈,但我担心这会使我的问题过于局限并且对我以外的任何人都毫无用处。此外,我实际上找到了问题的原因:在一些非常罕见的情况下,在使用某些 com 对象之前没有初始化上下文,这会弄乱系统,但错误只会在稍后出现。所以我确保在使用任何 com 对象之前始终初始化上下文,然后问题就消失了。

我仍然对有关线程安全的答案和我提出的解决方案感兴趣。或者这个问题应该因为过于本地化而被关闭?

最佳答案

您不需要在对象周围使用锁,因为 COM 线程的全部目的是让您在多线程环境中的生活更轻松和自动化(一旦您了解它的用途,并且注册表是否正确)。

在标准托管 .NET 方案中,您也不需要执行任何特定操作,即使释放 COM 对象也应该由垃圾收集器自动完成。所以你不应该需要一个 using 模式。

话虽这么说,底层非托管 COM 对象在使用一次后释放时可能会更好地工作,或者您的应用程序可能由于某种原因不能真正等待 GC 发生(例如,由于 hi usage ).在这些情况下,您可以使用 Marshal.ReleaseComObjectMarshal.FinalReleaseComObject强制释放使用过的 COM 对象,并使用包装器对象对其进行包装。

关于c# - COM 和线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13669347/

相关文章:

c# - X509Certificate2.FriendlyName 属性无法检索 Linux 上的证书标签

c# - 在 C# 中将 HTML 写入 WebBrowser 的正确方法是什么?

c# - 使用 COM+ 在 MSXML 和 .Net 之间互操作

java - 如何从 java 运行多线程 python 脚本?

c++ - 在lambda中锁定std::shared_ptr的复制操作

c# - 将参数传递给模态数据

javascript - 如何验证 JavaScript 代码在 C# 中是否有效

c++ - MSXML 方法是否获取其 BSTR 参数的内存所有权?

windows - Delphi 应用程序与偶尔崩溃的程序通信 - 供应商指责我的 Delphi 应用程序

c++ - 如果一个线程正在执行的仿函数被移动会发生什么?