2012-01-04 91 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