C#收集編程基本之過程和線程詳解。本站提示廣大學習愛好者:(C#收集編程基本之過程和線程詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是C#收集編程基本之過程和線程詳解正文
在C#的收集編程中,過程和線程是必備的基本常識,同時也是一個重點,所以我們要好好的控制一下。
一:概念
起首我們要曉得甚麼是”過程”,甚麼是“線程”,好,查一下baike。
過程:是一個具有必定自力功效的法式關於某個數據聚集的一次運動。它是操作體系靜態履行的根本單位,
在傳統的操作體系中,過程既是根本的分派單位,也是根本的履行單位。
線程:是"過程"中某個單一次序的掌握流。
關於這兩個概念,年夜家略微有個印象就好了,避免今後被面試官問到。
二:過程
framework外面對“過程”的根本操作的封裝照樣蠻好的,可以或許知足我們現實開辟中的根本運用。
<1> 獲得過程信息
framework中給我們獲得過程的方法照樣蠻多的,便可以依照Name獲得,也能夠依照ID獲得,也能夠獲得當地和長途的過程信息。
public Process[] GetProcess(string ip = "")
{
if (string.IsNullOrEmpty(ip))
return Process.GetProcesses();
return Process.GetProcesses(ip);
}
Process process = Process.GetProcessById(Convert.ToInt32(processID));
<2> 啟動和停滯過程
其實這個也沒啥好說的,不外有一個留意點就是Process中的"kill"和"CloseMainWindow"的差別。
windowMainWindow: 當我們翻開的Process是一個有界面的運用法式時,推舉應用此辦法,它相當於點擊了運用法式的封閉按鈕,是一個有序的終止運用法式的操作,而不像kill那末暴力。
kill:依據這個單詞估量年夜家都曉得啥意思吧,它的感化就是強迫封閉我們翻開的Process,常常會形成就是我們數據的喪失,所以說在萬不得已的情形下不要應用kill,固然在無圖形界面的運用法式中,kill是獨一可以或許停止Process的一個戰略。
<3> 過程操作的一個演示:
public class ProgessHelper { //主操作流程 public static void MainProcess() { ProgessHelper helper = new ProgessHelper(); var result = helper.GetProcess(); helper.ShowProcess(result.Take(10).ToArray()); Console.Write("\n請輸出您要檢查的過程:"); helper.ShowProcessSingle(Console.ReadLine()); Console.Write("\n請輸出您要開啟的法式:\t"); var name = helper.StartProcess(Console.ReadLine()); Console.WriteLine("法式曾經開啟,能否封閉?(0,1)"); if (Console.ReadLine() == "1") { helper.StopProcess(name); Console.WriteLine("封閉勝利。"); } } #region 獲得過程 /// <summary> /// 獲得過程 /// </summary> /// <param name="ip"></param> /// <returns></returns> public Process[] GetProcess(string ip = "") { if (string.IsNullOrEmpty(ip)) return Process.GetProcesses(); return Process.GetProcesses(ip); } #endregion #region 檢查過程 /// <summary> /// 檢查過程 /// </summary> /// <param name="process"></param> public void ShowProcess(Process[] process) { Console.WriteLine("過程ID\t過程稱號\t物理內存\t\t啟動時光\t文件名"); foreach (var p in process) { try { Console.WriteLine("{0}\t{1}\t{2}M\t\t{3}\t{4}", p.Id, p.ProcessName.Trim(), p.WorkingSet64 / 1024.0f / 1024.0f, p.StartTime, p.MainModule.FileName); } catch (Exception ex) { Console.WriteLine(ex.Message); } } } #endregion #region 依據ID檢查指定的過程 /// <summary> /// 依據ID檢查指定的過程 /// </summary> /// <param name="processID"></param> public void ShowProcessSingle(string processID) { Process process = Process.GetProcessById(Convert.ToInt32(processID)); Console.WriteLine("\n\n您要檢查的過程具體信息以下:\n"); try { var module = process.MainModule; Console.WriteLine("文件名:{0}\n版本{1}\n描敘{2}\n說話:{3}", module.FileName, module.FileVersionInfo.FileVersion, module.FileVersionInfo.FileDescription, module.FileVersionInfo.Language); } catch (Exception e) { Console.WriteLine(e.Message); } } #endregion #region 過程開啟 /// <summary> /// 過程開啟 /// </summary> /// <param name="fileName"></param> /// <returns></returns> public string StartProcess(string fileName) { Process process = new Process(); process.StartInfo = new ProcessStartInfo(fileName); process.Start(); return process.ProcessName; } #endregion #region 終止過程 /// <summary> /// 終止過程 /// </summary> /// <param name="name"></param> public void StopProcess(string name) { var process = Process.GetProcessesByName(name).FirstOrDefault(); try { process.CloseMainWindow(); } catch (Exception ex) { Console.WriteLine(ex.Message); } } #endregion }
快看,PPTV真的被我翻開了,嗯,8錯,Process照樣蠻好玩的。
這裡要留意一點:
我們在59行中加上了Try Catch,這是由於每一個Process都有一個MainModule屬性,但其實不是每個MainModule都能被C#獲得,
如會湧現以下的“謝絕拜訪”。
三: 線程
異樣線程的相干操作也曾經被framework外面的Thread完善的封裝,年夜年夜簡化了我們的任務量,經常使用的操作以下
<1> 啟動線程。
<2> 終止線程。
<3> 暫停線程。
<4> 歸並線程。
這個要說明一下,好比:t1線程在履行進程中須要期待t2履行完能力持續履行,此時我們就要將t2歸並到t1中去,也就是在t1的代碼塊中寫上t2.Join()便可。異樣Join中也能夠加上期待t2履行的時光,不論t2能否履行終了。
<5> 線程同步
估量年夜家也曉得,多線程處理了體系的吞吐量和呼應時光,同時也給我們留下了好比逝世鎖,資本爭用等成績,那末我們若何
處理這些成績呢?呵呵,Anders Hejlsberg 這位老先輩曾經給我們供給了許多的完成同步線程的類,好比Mutex,Monitor,
Interlocked和AutoResetEvent,固然在現實運用中,我們照樣愛好應用簡化版的lock,由於這玩意可以或許使編程簡化,同時使
法式看起來簡練清楚明了。
<6> 異樣我也舉個例子
public class ThreadHelper { public static void MainThread() { ThreadHelper helper = new ThreadHelper(100); Thread[] thread = new Thread[20]; for (int i = 0; i < 20; i++) { thread[i] = new Thread(helper.DoTransactions); thread[i].Name = "線程" + i; } foreach (var single in thread) { single.Start(); } } int balance; object obj = new object(); public ThreadHelper(int balance) { this.balance = balance; } #region 取款操作 /// <summary> /// 取款操作 /// </summary> /// <param name="amount"></param> public void WithDraw(int amount) { lock (obj) { if (balance <= 0) { Console.WriteLine("哈哈,曾經取完了"); return; } if (balance >= amount) { Console.WriteLine("取款前余額:{0},取款:{1},還殘剩額:{2}", balance, amount, balance - amount); balance = balance - amount; } else { Console.WriteLine("取款前余額:{0},取款:{1},還殘剩額:{2}", balance, balance, balance = 0); } } } #endregion #region 主動取款操作 /// <summary> /// 主動取款操作 /// </summary> public void DoTransactions(object obj) { int random = new Random().Next(4, 10); Thread.Sleep(5000); WithDraw(random); } #endregion }
當我們加上lock的時刻一切正常,然則當我們把lock去失落的時刻,看看線程們會有“爭用資本”的景象嗎?,鄙人圖中可以看到,湧現了以下的景象,
固然這不是我想看到的成果,假如在現實運用中會是何等難找的bug。
<8> 線程池
下面的例子中,我創立了20個線程來完成義務,好比在某些現實運用中,Client真個每一個要求Server都須要創立一個線程來處置,
那末當線程許多的時刻其實不是一件功德情,這會招致過度的應用體系資本而耗盡內存,那末天然就會引入“線程池”。
線程池:是一個在後台履行多個義務的聚集,他封裝了我們對線程的根本操作,我們能做的就只需把“進口辦法”丟給線程池就好了。
特色: 線程池有最年夜線程數限制,年夜小在分歧的機械上能否差別的,當池中的線程都是忙碌狀況,後入的辦法就會列隊,直至池中有余暇的線程來處置。
代碼: 修正後以下:
public static void MainThread() { ThreadHelper helper = new ThreadHelper(100); for (int i = 0; i < 20; i++) { ThreadPool.QueueUserWorkItem(new WaitCallback(helper.DoTransactions)); } //Thread[] thread = new Thread[20]; //for (int i = 0; i < 20; i++) //{ // thread[i] = new Thread(helper.DoTransactions); // thread[i].Name = "線程" + i; //} //foreach (var single in thread) //{ // single.Start(); //} }