我有这个遗留的第三方COM DLL。我将其注册到注册表,并将RCW添加到.NET/C#控制台应用程序中。注册表将用于COM的线程模型显示为 shows 。我的应用程序的全部目的是使用多线程并发提交多个请求并接收对此COM服务器的响应。
我正在使用SmartThreadPool进行线程管理,现在在每个线程中我都在为COM查找/请求提交步骤创建新的对象。但是,如果我查看COM服务器日志,请求将按顺序提交/处理。
问题出在哪里?
因此,我认为问题在于COM实际上是经过/STA配置的。但我的最终目标是让它起作用,所以我的问题,
这真的太让人困惑了,我快疯了!请注意,每个线程都在从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();
}
}发布于 2011-11-01 18:03:28
如果您所拥有的只是COM组件,并且它是STA组件,那么将无法使该组件服务调用的实例并发为。
但是,这并不妨碍您实例化组件的多个实例并调用多个实例。为此,您可能需要考虑使用COM+对象池并以这种方式获取组件的实例。
请注意,仅仅因为COM组件正在与之交谈的服务能够并发处理请求,这个问题就与客户端并发处理调用的能力完全不同。
假设您可以掌握代码,那么不可能说要在MTA或免费线程中运行它需要什么(后者更好);我们不知道实现细节或存储的状态(甚至API是什么样的)。
如果所有组件所做的都是发送请求和处理响应而不存储状态,那么这应该相当容易,这只是一个切换单元的问题。
但是,组件可能是STA有两个原因:
1)组件具有大量的状态,STA是确保状态不被并发调用破坏的一种方法;在这种情况下,使组件MTA/free线程化的工作将很困难,因为您必须保护所有东西,即使这样,您也可能无法从所有的并发检查中获得任何好处(尽管您可能会找到一种方法,以轻松线程安全的方式将代码转换为.NET代码)。
2)组件是用VB6编写的,或者是一种不支持MTA/免费线程组件的语言;在这种情况下,不可能更改单元模型,您必须有多个实例,或者将其转换为线程安全的.NET。
发布于 2011-11-01 18:19:53
您可能需要创建多个STA线程,每个线程都有自己的消息循环(*),每个线程都有自己的单元线程COM对象的实例。
您可以通过调用Thread.SetApartmentState来设置线程的单元状态。
(*)如果需要封送来自另一个线程的调用,则需要消息循环。
https://stackoverflow.com/questions/7967019
复制相似问题