gpt4 book ai didi

c# - COM、STA 和多线程

转载 作者:太空狗 更新时间:2023-10-30 01:24:59 26 4
gpt4 key购买 nike

我有这个遗留的第三方 COM DLL。我将其注册到注册表并将 RCW 添加到我的 .NET/C# 控制台应用程序。注册表将 COM 的线程模型 显示为单元。我的应用程序的全部目的是使用多线程并发提交多个请求并接收对此 COM 服务器的响应。

我正在使用 SmartThreadPool 进行线程管理,现在我在每个线程中为 COM 查找/请求提交步骤创建新对象。但是,如果我查看 COM 服务器日志,仍然会按顺序提交/处理请求。

问题出在哪里?

所以,我认为问题实际上在于 COM 是 Apartment/STA 配置的。但我的最终目标是让它发挥作用,所以我的问题是,

  1. 假设我能使用的只有这个 STA COM DLL 文件,是否有任何变通方法可以让它并行处理我的请求?

  2. 考虑到这样一个事实,当我并行运行我的控制台应用程序的两个实例时,最终服务器机器(COM DLL 实际与之连接和工作)中的日志实际上显示来自两个实例的请求是并行处理的在两个不同的 session 中。所以,最终的应用程序都是为了支持并行处理。 (我想这是一个幼稚的问题)假设我可以得到 COM 代码,让它支持 MTA 是不是很容易?

[这真的太令人困惑了,我快疯了!请注意,每个线程都从 COM DLL 文件创建自己的一组新对象,用于 COMServer 查找、请求、提交等。]

申请代码

public class start
{
public static void Main(string[] args)
{
StartProcessing();
}

private static void StartProcessing()
{
CoreProcessor pcr = new CoreProcessor();
pcr.start();
}
}

public class CoreProcessor
{
public static ManualResetEvent IsAllDone;
public static int NumberOfActiveThreads;
private SmartThreadPool TPool = new SmartThreadPool();
public void start()
{
IEnumerable<string> LstRequests = FileIO.GetAllRequestFileNames();
NumberOfActiveThreads = LstRequests.Count();
IsAllDone = new ManualResetEvent(false);
foreach(var reqName in LstRequests)
{
ReqInfo req = new ReqInfo(){RequestPath = reqName;};
TPool.QueueWorkItem(new WorkItemCallBack(req.ProcessRequest));
}
if(NumberOfActiveThreads > 0)
IsAllDone.WaitOne();
}
}

public class ReqInfo
{
public string RequestPath;
public void ProcessRequest()
{
ABC_COM_Request req = new ABC_COM_XMLUTIL().CreateRequest();
ABC_COM_Server svr = new ABC_COM_ServerLookup().lookup("serverhostname", 1099);
ABC_COM_Response resp = svr.submit(req);
if (InterLocked.Decrement(ref CoreProcessor.NumberOfActiveThreads) == 0)
CoreProcessor.IsAllDone.Set();
}
}

最佳答案

如果您只有 COM 组件并且它是一个 STA 组件,那么您无法执行任何操作来同时创建该组件服务调用的实例

但是,这不会阻止您实例化组件的多个实例 并调用多个实例。为此,您可能需要考虑使用 COM+ object pooling并以这种方式获取组件的实例。

请注意,仅仅因为与 COM 组件通信的服务能够并发处理请求,这是一个与客户端同时处理对的调用的能力完全不同的问题。

假设您可以拿到代码,就不可能说出让它在 MTA 或自由线程(后者更可取)中运行需要什么;我们不知道实现细节或存储的状态(甚至 API 是什么样的)。

如果组件所做的只是发送请求和处理响应而不存储状态,那么这应该相当容易,只需切换公寓即可。

但是,组件可能是 STA 的原因有两个:

1) 组件有很多状态,STA 是一种确保状态不会被并发调用破坏的方法;在这种情况下,使组件 MTA/自由线程化的工作将很困难,因为您必须保护所有内容,即使那样,由于可能必须进行的所有并发检查,您可能不会获得任何好处(尽管您可能会找到一种将代码转换为 .NET 代码的方法,这种方法很容易实现线程安全)。

2) 该组件是用VB6 或不支持MTA/自由线程组件的语言编写的;在这种情况下,不可能更改单元模型,您必须拥有多个实例或转换为线程安全的 .NET。

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

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com