c#:实现动态编译,并实现动态MutilProcess功能(来自python mutilprocess的想法)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c#:实现动态编译,并实现动态MutilProcess功能(来自python mutilprocess的想法)相关的知识,希望对你有一定的参考价值。

  由于之前一直遇到一些关于并行进行数据处理的时效果往往不好,不管是c#还是java程序都是一样,但是在Python中通过mutilprocess实现同样的功能时,却发现确实可以提高程序运行的性能,及服务器资源使用提高。python具体性能及mutilprocess用法,请参考:《Python:使用pymssql批量插入csv文件到数据库测试

  如有转载请标明原文地址:https://i.cnblogs.com/EditPosts.aspx?postid=7228337

  很久之前就设想如何在c#中实现多进程的方案,如今终于设计出了C#中动态实现多进程的方案:

技术分享

具体代码:

  1 using Microsoft.CSharp;
  2 using System;
  3 using System.CodeDom;
  4 using System.CodeDom.Compiler;
  5 using System.Collections.Generic;
  6 using System.Linq;
  7 using System.Reflection;
  8 using System.Text;
  9 
 10 namespace MutilProcessDemo
 11 {
 12     public class Program
 13     {
 14         static System.Timers.Timer timer = null;
 15 
 16         public static void Main(string[] args)
 17         {
 18             GenerateExe();
 19 
 20             timer = new System.Timers.Timer();
 21             timer.AutoReset = true;
 22             timer.Enabled = true;
 23             timer.Interval = 5000;
 24             timer.Elapsed += Timer_Elapsed;
 25 
 26 
 27             Console.WriteLine("Press Enter key to exit...");
 28             Console.ReadKey();
 29         }
 30 
 31         private static void DynamicCompiler()
 32         {
 33             // 1.CSharpCodePrivoder 
 34             CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider();
 35 
 36             // 2.ICodeComplier 
 37             ICodeCompiler objICodeCompiler = objCSharpCodePrivoder.CreateCompiler();
 38 
 39             // 3.CompilerParameters 
 40             CompilerParameters objCompilerParameters = new CompilerParameters();
 41             objCompilerParameters.ReferencedAssemblies.Add("System.dll");
 42             objCompilerParameters.GenerateExecutable = false;
 43             objCompilerParameters.GenerateInMemory = true;
 44 
 45             // 4.CompilerResults 
 46             CompilerResults cr = objICodeCompiler.CompileAssemblyFromSource(objCompilerParameters, GenerateCode());
 47 
 48             if (cr.Errors.HasErrors)
 49             {
 50                 Console.WriteLine("编译错误:");
 51                 foreach (CompilerError err in cr.Errors)
 52                 {
 53                     Console.WriteLine(err.ErrorText);
 54                 }
 55             }
 56             else
 57             {
 58                 // 通过反射,调用HelloWorld的实例 
 59                 Assembly objAssembly = cr.CompiledAssembly;
 60                 object objHelloWorld = objAssembly.CreateInstance("DynamicCodeGenerate.HelloWorld");
 61                 MethodInfo objMI = objHelloWorld.GetType().GetMethod("OutPut");
 62 
 63                 Console.WriteLine(objMI.Invoke(objHelloWorld, null));
 64             }
 65 
 66             Console.ReadLine();
 67         }
 68 
 69         static string GenerateCode()
 70         {
 71             StringBuilder sb = new StringBuilder();
 72             sb.Append("using System;");
 73             sb.Append(Environment.NewLine);
 74             sb.Append("namespace DynamicCodeGenerate");
 75             sb.Append(Environment.NewLine);
 76             sb.Append("{");
 77             sb.Append(Environment.NewLine);
 78             sb.Append(" public class HelloWorld");
 79             sb.Append(Environment.NewLine);
 80             sb.Append(" {");
 81             sb.Append(Environment.NewLine);
 82             sb.Append(" public string OutPut()");
 83             sb.Append(Environment.NewLine);
 84             sb.Append(" {");
 85             sb.Append(Environment.NewLine);
 86             sb.Append(" return \\"Hello world!\\";");
 87             sb.Append(Environment.NewLine);
 88             sb.Append(" }");
 89             sb.Append(Environment.NewLine);
 90             sb.Append(" }");
 91             sb.Append(Environment.NewLine);
 92             sb.Append("}");
 93 
 94             string code = sb.ToString();
 95             Console.WriteLine(code);
 96             Console.WriteLine();
 97 
 98             return code;
 99         }
100 
101 
102         private static void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
103         {
104             System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName("HelloWorld.exe");
105 
106             int maxProcessCount = 8;
107             // 如果超过了最大允许任务数据不再触发新的进程任务
108             if (processes.Length >= maxProcessCount)
109                 return;
110 
111             List<int> tasks = new List<int>();
112             Random random = new Random(1000);
113             for (int i = 0; i < maxProcessCount - processes.Length; i++)
114             {
115                 tasks.Add(random.Next(1000));
116             }
117 
118 
119             System.Threading.Tasks.Task[] taskItems = new System.Threading.Tasks.Task[tasks.Count];
120 
121             for (int i = 0; i < tasks.Count; i++)
122             {
123                 //TaskBase taskSubmit = new ParseMrToHdfsFileItemTask();
124                 //taskItems[i] = System.Threading.Tasks.Task.Factory.StartNew(taskSubmit.Submit, new ParseMrToHdfsFileItemTaskArgument() { Task = tasks[i], ComputeNode = this.ComputeNode }, TaskCreationOptions.PreferFairness);
125                 taskItems[i] = System.Threading.Tasks.Task.Factory.StartNew((object state) =>
126                 {
127                     System.Diagnostics.Process process = new System.Diagnostics.Process();
128                 //System.Diagnostics.Process process = System.Diagnostics.Process.Start("HelloWorld.exe", state.ToString());
129                 process.StartInfo = new System.Diagnostics.ProcessStartInfo();
130                     process.StartInfo.CreateNoWindow = true;
131                     process.StartInfo.UseShellExecute = false;
132                     process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
133                     process.StartInfo.Arguments = state.ToString();
134                     process.StartInfo.FileName = "HelloWorld.exe";
135                     process.Start();
136                     process.WaitForExit();
137                     process.Close();
138                     process.Dispose();
139                 }, tasks[i]);
140             }
141 
142             System.Threading.Tasks.Task.WaitAll(taskItems);
143         }
144 
145         private static void GenerateExe()
146         {
147             // 创建编译器对象
148             CSharpCodeProvider p = new CSharpCodeProvider();
149             ICodeCompiler cc = p.CreateCompiler();
150 
151             // 设置编译参数
152             CompilerParameters options = new CompilerParameters();
153             options.ReferencedAssemblies.Add("System.dll");
154             options.ReferencedAssemblies.Add("MutilProcessDemo.exe");
155             options.GenerateExecutable = true;
156             options.OutputAssembly = "HelloWorld.exe";
157 
158             //options.ReferencedAssemblies.Add("System.Windows.Forms.dll");
159             //options.EmbeddedResources.Add("Data.xml"); // 添加内置资源
160             //options.CompilerOptions += " /target:winexe";
161             //options.CompilerOptions += " /res:Resource1.res";
162             //options.CompilerOptions += " /win32icon:test.ico";
163 
164             // 创建源码
165 
166             // 1. 使用CodeDom创建源码
167             //CodeCompileUnit cu = new CodeCompileUnit();
168             //CodeNamespace Samples = new CodeNamespace("Samples");
169             //cu.Namespaces.Add(Samples);
170             //Samples.Imports.Add(new CodeNamespaceImport("System"));
171             //CodeTypeDeclaration Class1 = new CodeTypeDeclaration("Class1");
172             //Samples.Types.Add(Class1);
173             //CodeEntryPointMethod Start = new CodeEntryPointMethod();
174             //CodeMethodInvokeExpression cs1 = new CodeMethodInvokeExpression(
175             // new CodeTypeReferenceExpression("System.Console"), "WriteLine",
176             // new CodePrimitiveExpression("Hello World!")
177             // );
178             //Start.Statements.Add(new CodeExpressionStatement(cs1));
179             //Class1.Members.Add(Start);
180 
181             // 2. 直接指定源码字符串
182             string code = @"
183 using System;
184 using MutilProcessDemo;
185 
186 namespace Samples
187 {
188     public class Class1
189     {
190         static void Main(string[] args)
191         {
192             Console.WriteLine(""Hello, World!"");
193             MutilProcessDemo.Program.DoMethod(args);
194             Console.WriteLine(DateTime.Now.ToString());
195         }
196     }
197 }";
198             CodeSnippetCompileUnit codeSnippetCompileUnit = new CodeSnippetCompileUnit(code);
199 
200             // 开始编译
201             CompilerResults compilerResults = cc.CompileAssemblyFromDom(options, codeSnippetCompileUnit);
202 
203             // 显示编译信息
204             if (compilerResults.Errors.Count == 0)
205                 Console.WriteLine("{0}compiled ok!", compilerResults.CompiledAssembly.Location);
206             else
207             {
208                 Console.WriteLine("Complie Error:");
209                 foreach (CompilerError error in compilerResults.Errors)
210                     Console.WriteLine(" {0}", error);
211             }
212         }
213 
214         public static void DoMethod(string[] args)
215         {
216             System.Console.WriteLine("begin ..." + args[0]);
217 
218             for (int i = 0; i < int.Parse(args[0]); i++)
219             {
220                 System.Threading.Thread.Sleep(20);
221             }
222 
223             System.Console.WriteLine("end..." + args[0]);
224         }
225     }
226 }

上边的程序运行之后会在\\MutilProcessDemo\\bin\\Debug\\下出现两个可执行的.exe:HelloWorld.exe、MutilProcessDemo.exe。

参考文章:

c#动态编译,程序集的动态创建(http://www.360doc.com/content/14/1014/11/5054188_416763069.shtml)

以上是关于c#:实现动态编译,并实现动态MutilProcess功能(来自python mutilprocess的想法)的主要内容,如果未能解决你的问题,请参考以下文章

是否可以动态编译和执行 C# 代码片段?

c# 动态编译

C#执行js动态编译的方法

c#中如何动态添加菜单项并实现其点击?

C#开发的OpenRA动态加载插件DLL里的类实现

C#开发的OpenRA动态加载插件DLL里的类实现