2012-01-04 93 views
2

我有一个Windows服务,一直即使在大量并发工作多年运行没有任何问题下面的代码:CSharpCodeProvider,CompilerParameters.GenerateInMemory和CompilerResults.PathToAssembly:古怪的行为

CSharpCodeProvider codeProvider = new CSharpCodeProvider();   

CompilerParameters parameters = new CompilerParameters(); 
parameters.GenerateExecutable = false; 
parameters.GenerateInMemory = true; 
parameters.OutputAssembly = outputAssemblyFile;  

CompilerResults results = codeProvider.CompileAssemblyFromFile(parameters, "file.cs"); 

if (results.Errors.Count > 0) 
{ 
    Console.WriteLine("Compile ERROR"); 
} 
else 
{ 
    Console.WriteLine("Compile OK");   
    Console.WriteLine("Assembly Path:" + results.PathToAssembly); 
    Console.WriteLine("Assembly Name:" + results.CompiledAssembly.FullName);   
} 

通常,当代码已成功编译,因为parameters.GenerateInMemory设置为true,results.PathToAssembly为空(如MSDN中指定的)

其中一个问题是,有时代码已成功编译,但result.PathToAssembly不是null。此外,CompiledAssembly正在返回一个FileNotFoundException,但是当我检查由results.PathToAssembly指示的路径时,程序集确实在那里。然而,我不能确定它在那个特定时刻。

我重新启动该服务,一切都回到正轨。

有什么明显的原因要做到这一点?

思考,这可能是一些权限问题我试图在已经创建的组件,并设置文件只读重现该问题,但引起编译失败的原因。

+0

当结果=正在查找指定程序集的路径时,偶然会发生轻微的权限问题。也可以在代码中释放或处理新创建的对象..如果在导致此特定错误时可能存在某些缓存问题,我会发现它。 – MethodMan 2012-01-04 19:24:47

+0

为什么要设置'parameters.OutputAssembly'参数。 GenerateExecutable == false'? – 2012-01-04 20:16:53

+0

@ M.Babcock我想你的意思是parameters.GenerateInMemory = true。这是个好问题。 OutputAssembly正在设置,因为我们需要程序集(实际的文件)。我没有编写代码,因此我不知道GenerateInMemory部分。 – 2012-01-04 22:59:23

回答

1

当我编写GenerateInMemory==true编译结果时,应该在内存中生成文档,而不生成EXE或DLL文件 - 因此result.PathToAssembly==null

在这种情况下设置OutputAssembly的东西仍然是有意义:一个装配有即使它只是生活在记忆的名称。 GenerateExecutable告诉系统生成一个EXE或一个DLL,所以如果结果在内存中,它应该被忽略。

这是我理解理论的方式 - 实际发生的是无论GenerateInMemory的值是什么,都会生成DLL EXE文件,其名称由OutputAssembly指定并放置在当前目录中。

而且,看来该编译器对这个文件的多个操作 - 删除/创建/开/关。

这意味着,如果编译器代码由多个线程同时称它可能会失败,或者“找不到文件”或错误“文件正在使用”,因为在不同的线程文件操作会相互干扰。

如果代码的目的是为了在磁盘上生成的程序集文件的解决办法是:

parameters.GenerateExecutable = false; 
parameters.GenerateInMemory = false; 

,并没有指定OutputAssembly - 在这种情况下,系统的组件会自动生成一个唯一的名称(和程序集DLL),避免不同线程之间的冲突。该文件的路径可通过result.PathToAssembly访问。

+1

请注意,如果您设置GenerateExecutable = false并且GenerateInMemory = true,则编译器仍将基于OutputAssembly路径生成可执行文件,而忽略TempFiles参数。这在我的情况下导致了权限问题,因为可执行文件(据说没有生成)正在生成到当前目录(例如程序文件)。 – 2015-09-14 17:25:59