繁体   English   中英

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

[英]Call VB6 DLL from a multithreaded c# windows service application?

我正在运行需要调用VB6 dll的多线程Windows服务。 没有有关此VB6 dll的文档,并且该旧系统支持非常关键的业务流程。

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

我读过一个人说:

“如果要使用VB6,请小心一件事。如果要运行多线程服务,则必须更改线程模型以支持单元。VB仅支持多个单线程单元,但是.NET通常会运行完全免费的线程。调用VB6 DLL的线程必须与DLL兼容。”

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

我们如何使用从多线程C#Windows Service应用程序调用的VB6 dll?

当线程进入时,您是否要保存对象并稍后在新线程上重用它们? 如果可以,请为每个线程新鲜创建对象。 我们使用的数据层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();
}

你说

我正在运行需要调用VB6 dll的多线程Windows服务。 没有有关此VB6 dll的文档,并且该旧系统支持非常关键的业务流程。

同时你说

第一次(1º线程)时,此dll性能良好。 由于其他线程需要访问,因此它开始提供错误的结果。

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

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

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

这样,就VB6 DLL而言,它的运行与经过测试可运行的完全相同。


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

这篇有关多线程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 ,并且需要选择其他两个选项之一。

您可能需要看一下: 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对象的所有调用进行封送处理(并引发线程切换),在某些情况下,由于IP封送处理故障,Idispatch调用将失败。 因此,建议仅使用兼容公寓中的STA(因此使用VB6)对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM