为什么我的Windows服务启动csc.exe实例?

时间:2011-06-08 22:38:24

标签: c# .net

我在C#中编写了一个多线程的Windows服务。出于某种原因,每次生成一个线程时都会启动csc.exe。我怀疑它与线程本身有关,但事实上它是在每个线程的基础上发生的,并且这些线程是短暂的,这使得问题非常明显:许多csc.exe进程不断启动和停止。 / p>

性能仍然相当不错,但我希望如果我能消除这种情况会有所改善。但是,更令我担心的是McAfee正在尝试扫描csc.exe实例并最终杀死该服务,显然当一个实例在扫描中期退出时。我需要在商业上部署此服务,因此更改McAfee设置不是解决方案。

我认为我的代码中的某些内容正在触发动态编译,但我不确定是什么。其他人遇到这个问题?解决它的任何想法?

更新1:

根据@sixlettervariables的建议和链接进行进一步研究后,问题似乎源于XML序列化的实现,如Microsoft's documentation on XmlSerializer:

所示
  

为了提高性能,XML序列化基础结构动态生成程序集以序列化和反序列化指定的类型。

Microsoft在同一个文档中进一步说明了优化:

  

基础架构查找并重用这些程序集。仅当使用以下构造函数时才会出现此问题:

     

XmlSerializer.XmlSerializer(类型):

     

XmlSerializer.XmlSerializer(Type,String)

似乎表明只要使用了两个指定的构造函数之一,codegen和编译在第一次使用时只会发生一次。但是,我没有从这个优化中受益,因为我正在使用另一种形式的构造函数,特别是:

  

public XmlSerializer(Type type,Type [] extraTypes)

进一步阅读,事实证明这也恰好是我在代码执行时观察到的内存泄漏的可能解释。同样,来自同一个文档:

  

如果使用任何其他构造函数,则会生成同一程序集的多个版本,并且永远不会卸载,这会导致内存泄漏和性能下降。最简单的解决方案是使用前面提到的两个构造函数之一。否则,必须将程序集缓存在Hashtable中。

微软建议的两个解决方法对我来说是最后的选择。转到另一种形式的构造函数不是首选(我使用“extratypes”形式来序列化派生类,这是每个Microsoft的文档支持使用),我不确定我喜欢管理缓存的想法用于跨多个线程的程序集。

所以,我有sgen'd,并且看到生成的类型序列化程序的组合符按预期生成,但是当我的代码执行时,未加载sgen生成的程序集(在融合日志查看器中进行观察)和过程监控)。我正在探索为什么会这样。

更新2:

当我使用两个“友好的”XmlSerializer构造函数之一时,sgen'd程序集加载正常(请参阅上面的Update 1)。例如,当我使用XmlSerializer(Type)时,sgen'd程序集加载并且不执行运行时codegen /编译。但是,当我使用XmlSerializer(Type, Type[])时,程序集不会加载。找不到任何合理的解释。

所以我正在恢复使用其中一个受支持的构造函数和sgen'ing。这种组合消除了我的原始问题(启动csc.exe),以及另一个相关问题(上面的Update 1中提到的XmlSerializer引起的内存泄漏)。但是,它确实意味着我必须为派生类型(在基类型上使用XmlInclude)恢复不太理想的序列化形式,直到框架中的某些更改来解决这种情况。

1 个答案:

答案 0 :(得分:14)

心灵调试:

If this is the case you can build these XML Serializer Assemblies a-priori.