从多线程c#windows服务应用程序调用VB6 DLL?

时间:2009-07-03 20:40:35

标签: c# vb6 .net-2.0 integration legacy

我正在运行需要调用VB6 dll的多线程Windows服务。没有关于这个VB6 dll的文档,这个遗留系统支持非常关键的业务流程。

第一次(第一个线程),这个dll表现良好。由于其他线程需要访问,因此开始提供错误的结果。

我读了一个人说:

  

“如果你使用VB6,请注意一件事。你的线程   如果你是的话,模型将不得不改变以支持公寓   运行多线程服务。 VB只支持多个   单线程公寓,但.NET运行完全免费的线程   一般。调用VB6 DLL的线程需要   兼容DLL。“

团队中的另一个人给了我一个想法,将这个ddl放在一个独立的应用程序域中。但我不确定。

我们如何使用从多线程c#windows服务应用程序调用的VB6 dll?

4 个答案:

答案 0 :(得分:2)

当线程进入时,您是否保存对象并在以后的新线程上重用它们?如果可以,为每个线程创建新鲜的对象。我们有这样的情况,我们使用的是数据层dll。如果在一个线程上创建连接,则不能从另一个线程使用它。如果在每个线程上创建一个新连接,它可以正常工作。

如果创建对象的速度很慢,请查看ThreadPool类和ThreadStatic属性。 Threadpool会一遍又一遍地重复使用同一组线程来完成工作,而ThreadStatic允许您创建一个仅存在于一个线程的对象。例如

[ThreadStatic]
public static LegacyComObject myObject;

当请求进入时,将其转换为作业并将其排入线程池中。作业启动时,检查静态对象是否已初始化;

void DoWork()
{ 
    if (myObject == null)
    { 
        // slow intialisation process
        myObject = New ...
    }

    // now do the work against myObject
    myObject.DoGreatStuff();
}

答案 1 :(得分:1)

你说

  

我正在运行多线程窗口   需要调用VB6 DLL的服务。   没有关于此的文档   VB6 dll和这个遗留系统   支持一项非常关键的业务   过程

同时你说

  

第一次(1º线程),这个dll   表现很好。正如其他线程所需   访问,它开始提供错误   结果

我确信管理层已经意识到您所看到的失败,因为支持关键业务流程的代码是旧的且没有文档的,并且正在以一种从未打算使用的方式使用,并且从未测试过使用过。我敢打赌它之前从未经过过.NET测试,是吗?

这是我的建议,这与我实际实施的内容类似:

VB6 DLL期望在单个线程上调用。 不要让它失望! 当你的服务启动时,让它启动一个相应类型的线程(我不能说,因为我故意忘记了所有的STA / MTA的东西)。将请求排队到该线程以访问VB6 DLL。所有这些访问都通过单线程进行。

就这一点而言,就VB6 DLL而言,它的运行方式与测试运行完全一样。


顺便说一下,这与我实施的略有不同。我有一个Web服务,而不是Windows服务。我有一个C DLL,而不是VB6,它不是COM。我只是将对事物的所有访问重构为一个类,然后在每个公共方法周围放置锁定语句。

答案 2 :(得分:0)

This article on multithreading Visual Basic 6 DLL's提供了一些见解。它说:

  

制作ActiveX DLL项目   多线程,选择所需的   “常规”选项卡上的线程选项   “项目属性”对话框。

This article说有三种可供选择的型号:

One thread of execution 
Thread pool with round-robin thread assignment 
Every externally created object is on its own thread 

我假设默认值为one thread of execution,并且需要选择其他两个选项中的一个。

答案 3 :(得分:0)

您可能需要查看此内容:linky

这是一个引起我注意的片段:

  

VB6 COM对象是STA对象,这意味着它们必须在STA线程上运行。   您确实从两个MTA线程创建了该对象的两个实例,但该对象本身将在单个(创建的COM(OLE))STA上运行   线程,来自两个MTA线程的访问将被封送和同步。   所以你应该做的是,将线程初始化为STA,以便每个对象在他自己的STA线程上运行而不用编组,你   会好的。

     

无论如何,VB风格的COM对象总是STA。现在为了防止公寓编组和线程切换你需要创建   STA中的实例初始化了公寓。   另请注意,在Main上设置[MTAThread]属性时,可以在创建时有效地将主线程初始化为MTA   来自MTA线程COM的STA对象的实例将创建一个单独的(非托管)线程并将其初始化为STA(这称为   默认STA),所有对来自MTA线程的STA对象的调用都将被封送(并产生线程切换),在某些情况下,Idispatch调用   由于IP编组故障将失败。   因此建议仅使用来自兼容公寓的STA(以及VB6)对象。