我正在运行需要调用VB6 dll的多线程Windows服务。没有关于这个VB6 dll的文档,这个遗留系统支持非常关键的业务流程。
第一次(第一个线程),这个dll表现良好。由于其他线程需要访问,因此开始提供错误的结果。
我读了一个人说:
“如果你使用VB6,请注意一件事。你的线程 如果你是的话,模型将不得不改变以支持公寓 运行多线程服务。 VB只支持多个 单线程公寓,但.NET运行完全免费的线程 一般。调用VB6 DLL的线程需要 兼容DLL。“
团队中的另一个人给了我一个想法,将这个ddl放在一个独立的应用程序域中。但我不确定。
我们如何使用从多线程c#windows服务应用程序调用的VB6 dll?
答案 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而言,它的运行方式与测试运行完全一样。
答案 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)对象。