正在c#程序優化時,若是多線程效果不佳的狀況下,也會使用多進程的方案,以下:c#
System.Threading.Tasks.Task task=System.Threading.Tasks.Task.Factory.StartNew( (object mystate) => { Process process = Process.Start("AutoCollectMrMultipleProcess.exe", mystate.ToString()); process.WaitForExit(); } , collectPathItems.Dequeue())
使用c#中的Process開啓線程,並運行一個c#編譯的一個Console的業務工程,Console.exe經過接收參數決定並行進程中的每一個進程處理具體的任務:例如,實現一個多進程下載,傳遞給每一個進程.exe的參數就是待採集的路徑。多線程
通常開闢的進程任務數也是要有限制的開,好比開闢進程數與計算機內核數同樣Enviroment.ProcessCount。那麼問題來了優化
假設:咱們有25個帶下待的任務,有的任務是1個小時左右才能完成、有的10分鐘就完成了,如何確保一個完整的業務代碼中去確保10分鐘完成後,發現當前的進程數還未達到最大數,並且還有待處理任務,就繼續開闢新的下載進程任務。spa
假設用A:已經開闢了3個AutoCollectMrMultipleProcess.exe,用戶B去進行本身的採集任務時,容許開闢的進程數爲:Enviroment.ProcessCount-3(若是該值已經小於等於0,就再也不開闢,進入等待)。線程
實現代碼:code
int maxProcessCount = Enviroment.ProcessCount; List<System.Threading.Tasks.Task> taskItems = new List<System.Threading.Tasks.Task>(); Queue<string> collectPathIetms=new Queue<string>();
// 初始化下載任務記錄start
。。。
// 初始化下載任務記錄end
int cursor = 0; while (!(collectPathItems.Count == 0 && taskItems.Count == 0)) { foreach (System.Threading.Tasks.Task taskItem in new List<System.Threading.Tasks.Task>(taskItems)) { if (taskItem.Status == System.Threading.Tasks.TaskStatus.Canceled || taskItem.Status == System.Threading.Tasks.TaskStatus.Faulted || taskItem.Status == System.Threading.Tasks.TaskStatus.RanToCompletion) { taskItems.Remove(taskItem); } } // 若是collectPathItems.Count == 0,則不會有新的任務被添加進來,所以不須要執行下邊其餘代碼。 // 而只須要等待上邊的任務完成跳出循環便可。 if (collectPathItems.Count == 0) { Thread.Sleep(30 * 1000); continue; } Process[] processItems = Process.GetProcessesByName("AutoCollectMrMultipleProcess"); if (processItems.Length >= maxProcessCount) { Thread.Sleep(30 * 1000); continue; } int dequeueCount = ((maxProcessCount - processItems.Length) > collectPathItems.Count) ? collectPathItems.Count : (maxProcessCount - processItems.Length); for (int i = 0; i < dequeueCount; i++) { taskItems.Add(System.Threading.Tasks.Task.Factory.StartNew( (object mystate) => { Process process = Process.Start("AutoCollectMrMultipleProcess.exe", mystate.ToString()); process.WaitForExit(); } , collectPathItems.Dequeue()) ); }
// sleep 30 seconds... Thread.Sleep(30 * 1000); cursor++; }