My question is around the .NET 4.6 CSharpCodeProvider
class and if it is thread-safe. I have a set of objects based on a FinancvialInstrument
class which in turn generates a C# class in order to calculate the value of the financial product. Ideally, we would like to run execution of these generated classes in parallel but when doing so we get an error. The following is the code we use to build and execute the generated class. Source is a string that contains the C# code
public void RunCode(string Source)
{
var cd = new CSharpCodeProvider();
CompilerParameters compiler_parameters = new CompilerParameters();
var exePath = Assembly.GetExecutingAssembly().Location;
var assemblyFolder = System.Reflection.Assembly.GetAssembly(this.GetType()).CodeBase.ToString();
assemblyFolder = Path.GetDirectoryName(assemblyFolder);
assemblyFolder = assemblyFolder.Replace(@"file:\", "");
var assemRefs = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
var references = new List<string>();\\
foreach (var assemblyName in assemRefs)
references.Add(assemblyName.Name + ".dll");
foreach (var t in references)
{
var localName = Path.Combine(assemblyFolder, t);
if (File.Exists(localName))
compiler_parameters.ReferencedAssemblies.Add(localName);
}
compiler_parameters.ReferencedAssemblies.Add(exePath);
compiler_parameters.GenerateInMemory = true;
compiler_parameters.GenerateExecutable = false;
compiler_parameters.GenerateInMemory = true;
compiler_parameters.IncludeDebugInformation = true;
compiler_parameters.WarningLevel = 1;
compiler_parameters.TreatWarningsAsErrors = false;
compiler_parameters.CompilerOptions = "/optimize";
var executingAssembly = Assembly.GetExecutingAssembly();
compiler_parameters.ReferencedAssemblies.Add(executingAssembly.Location);
CompilerResults compileResults;
compileResults = cd.CompileAssemblyFromSource(compiler_parameters, Source);
}
When run in a normal for loop as follows
foreach(var source in SourceList).
RunCode(source)
all works ok but when we try and execute the code in parallel as
parralell.foreach(SourceList, x => RunCode(x));
we get the following error when calling CompileAssemblyFromSource
System.ArgumentException occurred HResult=0x80070057 Message=The file name 'C:\Users\s.price\AppData\Local\Temp\2\zrnpj1cs.0.cs' was already in the collection. Parameter name: fileName Source=System StackTrace: at System.CodeDom.Compiler.TempFileCollection.AddFile(String fileName, Boolean keepFile) at System.CodeDom.Compiler.TempFileCollection.AddExtension(String fileExtension, Boolean keepFile) at Microsoft.CSharp.CSharpCodeGenerator.FromSourceBatch(CompilerParameters options, String[] sources) at Microsoft.CSharp.CSharpCodeGenerator.System.CodeDom.Compiler.ICodeCompiler.CompileAssemblyFromSourceBatch(CompilerParameters options, String[] sources)
It looks to us like the CSharpCodeProvider may not be thread-safe. Is this the case and if so is there an alternative approach to get around this?
Thanks for any help
Regards
Steve
User contributions licensed under CC BY-SA 3.0