Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 4.0 c#windows服务中vb6 COM dll使用的可用内存_C# 4.0_Service_Vb6 - Fatal编程技术网

C# 4.0 c#windows服务中vb6 COM dll使用的可用内存

C# 4.0 c#windows服务中vb6 COM dll使用的可用内存,c#-4.0,service,vb6,C# 4.0,Service,Vb6,我对使用解决方案中引用的VB6 COM dll的windows服务有问题 该服务是执行任务的计划程序。每个任务都在一个线程中执行,因此它允许用户同时执行一些任务 线程启动时,将在C#中创建一个对象(在名为C#u AUTO的vb6 dll中),并使用“New”语法。此对象的构造函数创建其他对象来执行任务。任务完成后,C_的析构函数将使用set…=没有什么。对象C_AUTO被破坏,线程也被破坏 我的问题是,当服务执行另一个任务时,另一个线程被创建为另一个C_AUTO对象。我添加了一个代码段,它在一个

我对使用解决方案中引用的VB6 COM dll的windows服务有问题

该服务是执行任务的计划程序。每个任务都在一个线程中执行,因此它允许用户同时执行一些任务

线程启动时,将在C#中创建一个对象(在名为C#u AUTO的vb6 dll中),并使用“New”语法。此对象的构造函数创建其他对象来执行任务。任务完成后,C_的析构函数将使用set…=没有什么。对象C_AUTO被破坏,线程也被破坏

我的问题是,当服务执行另一个任务时,另一个线程被创建为另一个C_AUTO对象。我添加了一个代码段,它在一个文件中写入内存指针的值,这些值是相同的,因此所有由C_AUTO创建的对象都不会被销毁

是否有其他方法可以加载VB6 dll而不使用“New”语法,该语法允许我在任务完成时卸载所有对象?因为几天后,服务消耗了大量内存,任务崩溃


感谢您的帮助

关于VB6对象,有几个令人不快的实现细节使得它们难以在C#服务中正确使用。VB6对象是单元线程化的COM对象。这是一个昂贵的词,意味着它们不是线程安全的,COM确保它们以线程安全的方式使用

C#服务几乎总是创建不适合单元线程对象的线程。COM将创建一个新线程,为这样的对象提供一个安全的家。这很昂贵,一个新线程需要1兆字节的虚拟内存

此外,只有在垃圾回收器运行时,才会卸载这样的对象(线程只会停止运行)。如果您对VB6对象进行了大量调用,但自己没有分配大量.NET对象,则很容易遇到问题。这会阻止GC频繁运行,从而避免所有这些线程被创建并占用大量虚拟内存而带来的麻烦。当你创建了大约1800个时,你会得到一个OOM-kaboom

具体的解决办法是:

  • 在启动线程之前,使用Thread.SetApartmentState()方法将线程切换到STA。这会阻止COM创建该辅助线程。请注意,常见的服务技术(如使用计时器来运行服务)并不适用,您必须在OnStart()方法中创建一个线程

  • 您可能需要调用Application.Run()来启动消息循环,这是STA线程的要求。这在服务中往往有点棘手,您从项目模板获得的帮助很少,无法将管道安装到位。您可以不用泵送就离开,但必须确保在创建VB6对象的同一线程上对该对象进行所有调用。错误的诊断是死锁

  • 如果确定GC的运行频率不够高(使用Perfmon.exe查看.NET计数器),则可能需要帮助并调用GC.Collect()以卸载VB6对象


要把所有东西都放在这里可不是那么容易。如果您一直在考虑更新VB6代码,那么现在就是一个好时机。

关于VB6对象,有几个令人不快的实现细节,使得它们难以在C#服务中正确使用。VB6对象是单元线程化的COM对象。这是一个昂贵的词,意味着它们不是线程安全的,COM确保它们以线程安全的方式使用

C#服务几乎总是创建不适合单元线程对象的线程。COM将创建一个新线程,为这样的对象提供一个安全的家。这很昂贵,一个新线程需要1兆字节的虚拟内存

此外,只有在垃圾回收器运行时,才会卸载这样的对象(线程只会停止运行)。如果您对VB6对象进行了大量调用,但自己没有分配大量.NET对象,则很容易遇到问题。这会阻止GC频繁运行,从而避免所有这些线程被创建并占用大量虚拟内存而带来的麻烦。当你创建了大约1800个时,你会得到一个OOM-kaboom

具体的解决办法是:

  • 在启动线程之前,使用Thread.SetApartmentState()方法将线程切换到STA。这会阻止COM创建该辅助线程。请注意,常见的服务技术(如使用计时器来运行服务)并不适用,您必须在OnStart()方法中创建一个线程

  • 您可能需要调用Application.Run()来启动消息循环,这是STA线程的要求。这在服务中往往有点棘手,您从项目模板获得的帮助很少,无法将管道安装到位。您可以不用泵送就离开,但必须确保在创建VB6对象的同一线程上对该对象进行所有调用。错误的诊断是死锁

  • 如果确定GC的运行频率不够高(使用Perfmon.exe查看.NET计数器),则可能需要帮助并调用GC.Collect()以卸载VB6对象


要把所有东西都放在这里可不是那么容易。如果您一直在考虑更新VB6代码,那么现在就是一个好时机。

感谢您的回复,但第一个解决方案(STA)和最后一个解决方案(GC.Collect)都不起作用。指针的id始终相同。是否有一个程序(perfom或其他)来显示程序创建的实例?感谢您的回复,但第一个解决方案(STA)和最后一个解决方案(GC.Collect)都不起作用。指针的id始终相同。是否有一个程序(perfom或其他程序)来显示程序创建的实例?