8

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

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

我读到一个人说:

“如果您使用的是 VB6,请注意一件事。如果您正在运行多线程服务,您的线程模型将不得不更改以支持单元。VB 仅支持多个单线程单元,但 .NET 可以正常运行完全自由线程. 调用 VB6 DLL 的线程需要与 DLL 兼容。”

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

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

4

4 回答 4

2

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

如果创建对象很慢,请查看 ThreadPool 类和 ThreadStatic 属性。线程池一遍又一遍地回收同一组线程来完成工作,而 ThreadStatic 允许您创建一个仅存在于一个线程的对象。例如

[ThreadStatic]
public static LegacyComObject myObject;

当一个请求进来时,把它变成一个作业并在你的线程池中排队。作业开始时,检查静态对象是否初始化;

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

    // now do the work against myObject
    myObject.DoGreatStuff();
}
于 2009-07-03T21:55:14.973 回答
1

你说

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

同时你说

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

我会非常确定管理层意识到您所看到的失败,因为支持关键业务流程的代码是旧的且未记录的,并且正在以一种从未打算使用的方式使用,并且从未经过测试使用。我敢打赌,它之前也从未经过测试可以从 .NET 中使用,是吗?

这是我的建议,这与我实际实现的类似:

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

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


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

于 2009-07-04T01:57:16.170 回答
0

这篇关于多线程 Visual Basic 6 DLL 的文章提供了一些见解。它说:

要使 ActiveX DLL 项目具有多线程,请在“项目属性”对话框的“常规”选项卡上选择所需的线程选项。

这篇文章说有三种可能的模型可供选择:

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

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

于 2009-07-03T20:52:56.533 回答
0

你可能想看看这个:linky

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

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

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

于 2009-07-03T21:05:37.350 回答