【发布时间】:2013-12-01 03:18:17
【问题描述】:
我目前正在研究 .Net Framework 2.0 Windows 服务 (C#) 中存在的问题,该服务具有 X 个运行访问 COM 组件的 MTA 线程。每个线程都初始化它自己的 com 组件对象实例。 com 组件对象没有任何 UI 元素。它只是与 sql server 数据库和具有 com 接口的 C# dll 通信的业务逻辑,后者依次进行套接字通信和访问同一个 sql server 数据库。
通过我的研究,我发现您不应该在 MTA 线程上实例化 STA COM 组件,但我找不到任何具体的文字来说明这样做的危险是什么,或者这可能是我不明白的事实COM 线程单元很好。
上面描述的模型会不会有并发问题?即使每个 MTA 线程都在创建它自己的 STA COM 对象?
编辑
我们实际遇到的问题是以下代码块中连接字符串的设置器中的对象引用未设置为对象错误的实例。这发生在由 c++ COM 对象调用的 C# COM 对象中:
IDbConnection connection;
//Code omitted for brevity where connection is initialized
connection.ConnectionString = myConnectionString;
异常类型:System.NullReferenceException 消息:对象 引用未设置为对象的实例。数据: System.Collections.ListDictionaryInternal TargetSite:无效 ConnectionString_Set(System.String) 在 System.Data.OracleClient.OracleConnection.ConnectionString_Set(字符串 值)在 System.Data.OracleClient.OracleConnection.set_ConnectionString(字符串 值)
【问题讨论】:
-
所有这些对象都存在于同一个线程上——当您第一次在 MTA 单元中创建 STA 组件时,COM 运行时已经为此目的创建了一个 STA 线程。对这些组件中的任何一个的任何调用都会被编组到该 STA 线程,在那里执行(以先到先服务的方式),并且任何结果都被编组回调用者的 MTA 线程。这种并发丢失是否是您设计中的问题,由您决定。
-
我对真正的并发问题更好奇,因为线程在内存方面相互踩踏而发生奇怪的事情。在这一点上,缺乏并发性不是问题。我只是想确保程序不会崩溃。
-
问题很可能出在“为简洁起见省略代码”的某个地方。
connection在您尝试分配给它的ConnectionString属性时为空,因此它毕竟没有被初始化,尽管您保证相反。找出原因。 -
真的没有那么多。我会发布它。连接不为空。我已经验证不是。仅供参考,它似乎与在 MTA 而不是 STA 中运行这些线程有关。由于我进行了此更改,因此不再抛出此错误。
-
你必须小心在你控制的 STA 线程上实例化 COM 对象——一旦 STA 线程退出,那些 COM 对象就消失了——所以如果另一个线程试图访问它们,你可以运行进入“COM 对象已与其底层 RCW 分离且无法使用”的问题。