c#:实现动态编译,并实现动态MultiProcess功能(来自python multiprocess的想法)
由于之前一直遇到一些关于并行进行数据处理的时效果往往不好,不管是c#还是java程序都是一样,但是在Python中通过multiprocess实现同样的功能时,却发现确实可以提高程序运行的性能,及服务器资源使用提高。python具体性能及multiprocess用法,请参考:《Python:使用pymssql批量插入csv文件到数据库测试》
如有转载请标明原文地址:http://www.cnblogs.com/yy3b2007com/p/7228337.html
很久之前就设想如何在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"); 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。
实战:
1 public class Program_ForInsertATU : BaseDao 2 { 3 static readonly BuildingsBO buildBO = new BuildingsBO(); 4 static readonly FingerPrintDatabaseBO fingerPrintDatabaseBO = new FingerPrintDatabaseBO(); 5 static readonly GridMappingBuildingBO gridMappingBuildingBO = new GridMappingBuildingBO(); 6 static readonly SiteBO siteBO = new SiteBO(); 7 static NLog.Logger logger = new NLog.LogFactory().GetCurrentClassLogger(); 8 9 private static void GenerateExe() 10 { 11 // 创建编译器对象 12 CSharpCodeProvider p = new CSharpCodeProvider(); 13 ICodeCompiler cc = p.CreateCompiler(); 14 15 // 设置编译参数 16 CompilerParameters options = new CompilerParameters(); 17 options.ReferencedAssemblies.Add("System.dll"); 18 options.ReferencedAssemblies.Add("System.Data.Linq.dll"); 19 options.ReferencedAssemblies.Add("System.Data.dll"); 20 options.ReferencedAssemblies.Add("System.Core.dll"); 21 22 options.ReferencedAssemblies.Add("Dx.Business.dll"); 23 options.ReferencedAssemblies.Add("Dx.Model.dll"); 24 options.ReferencedAssemblies.Add("Dx.Utility.dll"); 25 options.ReferencedAssemblies.Add("Dx.Configuration.dll"); 26 options.ReferencedAssemblies.Add("Dx.IDAL.dll"); 27 options.ReferencedAssemblies.Add("Dx.DataAccess.dll"); 28 options.ReferencedAssemblies.Add("Dx.Data.dll"); 29 options.ReferencedAssemblies.Add("Dx.Framework.dll"); 30 options.ReferencedAssemblies.Add("ICSharpCode.SharpZipLib.dll"); 31 options.ReferencedAssemblies.Add("Microsoft.CSharp.dll"); 32 33 options.EmbeddedResources.Add("HelloWorld.exe.config"); 34 //options.CompilerOptions += " /target:winexe"; 35 //options.CompilerOptions += " /res:Resource1.res"; 36 //options.CompilerOptions += " /win32icon:test.ico"; 37 38 options.GenerateExecutable = true; 39 options.OutputAssembly = "HelloWorld.exe"; 40 41 // 2. 直接指定源码字符串 42 string code = @" 43 using System; 44 using System.Collections.Generic; 45 using System.Linq; 46 using System.Text; 47 using System.IO; 48 using System.Data; 49 using System.Data.SqlClient; 50 using System.Threading; 51 using System.Threading.Tasks; 52 53 using Dx.Data; 54 using Dx.Business.Signal; 55 using Dx.Model.FingerprintDatabase; 56 using Dx.Business; 57 using Dx.Model; 58 using Dx.Utility; 59 using Dx.Configuration; 60 using Dx.Business.FingerprintDatabase.BO; 61 using Dx.Business.ATU.Parse; 62 using Dx.Framework.Utils; 63 using System.Text.RegularExpressions; 64 using ICSharpCode.SharpZipLib.GZip; 65 using System.Diagnostics; 66 using Dx.Business.Scheme; 67 using Dx.Business.ATU; 68 using Dx.Business.SiChuan; 69 using Dx.Model.SiChuan; 70 using System.CodeDom; 71 using System.CodeDom.Compiler; 72 using Microsoft.CSharp; 73 74 namespace Samples 75 { 76 public class Class1 77 { 78 static void Main(string[] args) 79 { 80 ConfigurationManger.Init(ConfigurationType.WindowsService); 81 EnumsRegister.Register(); 82 83 Dx.Business.SiChuan.GridInnerDoorAnalysis.GridInnerDoorAnalysis bo=new Dx.Business.SiChuan.GridInnerDoorAnalysis.GridInnerDoorAnalysis(); 84 bo.ComputeGridInnerDoor(args[0]); 85 } 86 } 87 }"; 88 CodeSnippetCompileUnit codeSnippetCompileUnit = new CodeSnippetCompileUnit(code); 89 90 // 开始编译 91 CompilerResults compilerResults = cc.CompileAssemblyFromDom(options, codeSnippetCompileUnit); 92 93 // 显示编译信息 94 if (compilerResults.Errors.Count == 0) 95 Console.WriteLine("{0} compiled ok!", compilerResults.CompiledAssembly.Location); 96 else 97 { 98 Console.WriteLine("Complie Error:"); 99 foreach (CompilerError error in compilerResults.Errors) 100 Console.WriteLine(" {0}", error); 101 } 102 } 103 104 public static void SubmitTask(object state) 105 { 106 List<string> ids = state as List<string>; 107 108 System.Threading.Tasks.Task[] taskItems = new System.Threading.Tasks.Task[ids.Count]; 109 110 for (int i = 0; i < ids.Count; i++) 111 { 112 taskItems[i] = System.Threading.Tasks.Task.Factory.StartNew((object argument) => 113 { 114 System.Diagnostics.Process process = new System.Diagnostics.Process(); 115 116 process.StartInfo = new System.Diagnostics.ProcessStartInfo(); 117 process.StartInfo.CreateNoWindow = true; 118 process.StartInfo.UseShellExecute = false; 119 process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; 120 process.StartInfo.Arguments = argument.ToString(); 121 process.StartInfo.FileName = "HelloWorld.exe"; 122 123 process.Start(); 124 125 //Console.WriteLine(process.ProcessName); 126 process.WaitForExit(); 127 process.Close(); 128 process.Dispose(); 129 }, ids[i]); 130 } 131 132 System.Threading.Tasks.Task.WaitAll(taskItems); 133 } 134 135 public static void Main(string[] args) 136 { 137 ConfigurationManger.Init(ConfigurationType.WindowsService); 138 EnumsRegister.Register(); 139 140 Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); 141 142 GenerateExe(); 143 144 List<BuildingVector> allBuildingVectors = buildBO.GetAllBuildingsAsGridInnerDoorAnalysis(); 145 146 // 将 指纹库数据拷贝到GridMappingBuildings 147 // gridMappingBuildingBO.CopyFingerPrinterDatabase(); 148 149 List<string> tasks = new List<string>(); 150 int take = 25; 151 for (var i = 0; i <= allBuildingVectors.Count / take; i++) 152 { 153 tasks.Add(string.Join(",", allBuildingVectors.Skip(i * take).Take(take).Select(m => m.BuildingID).ToArray())); 154 } 155 156 int skipCount = 0; 157 158 while (true) 159 { 160 System.Diagnostics.Process[] processes2 = System.Diagnostics.Process.GetProcessesByName("HelloWorld"); 161 162 int maxProcessCount = 36; 163 // 如果超过了最大允许任务数据不再触发新的进程任务 164 if (processes2.Length >= maxProcessCount) 165 { 166 Thread.Sleep(1000); 167 continue; 168 } 169 170 // submit task 171 int submitTaskCount = maxProcessCount - processes2.Length; 172 List<string> submitTasks = tasks.Skip(skipCount).Take(submitTaskCount).ToList(); 173 174 if(submitTasks.Count==0){ 175 break; 176 } 177 178 System.Threading.ThreadPool.QueueUserWorkItem(SubmitTask, submitTasks); 179 Thread.Sleep(5000); 180 skipCount += submitTaskCount; 181 182 Console.WriteLine("complete task count:{0}*25,total task count:{1}*25", skipCount, tasks.Count); 183 } 189 190 Console.WriteLine("Complete..."); 191 Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); 192 Console.ReadKey(); 193 }
}
参考文章:
c#动态编译,程序集的动态创建(http://www.360doc.com/content/14/1014/11/5054188_416763069.shtml)
基础才是编程人员应该深入研究的问题,比如:
1)List/Set/Map内部组成原理|区别
2)mysql索引存储结构&如何调优/b-tree特点、计算复杂度及影响复杂度的因素。。。
3)JVM运行组成与原理及调优
4)Java类加载器运行原理
5)Java中GC过程原理|使用的回收算法原理
6)Redis中hash一致性实现及与hash其他区别
7)Java多线程、线程池开发、管理Lock与Synchroined区别
8)Spring IOC/AOP 原理;加载过程的。。。
【+加关注】。