08年9月入學,12年7月畢業,結束了我在軟體學院愉快豐富的大學生活。此系列是對四年專業課程學習的回顧,索引參見:http://blog.csdn.net/xiaowei_cqu/article/details/7747205
線程與進程
通過查閱MSDN中C#關於Process類和Thread類的內容設計如下要求的一段程式:
在程式中開啟兩個後台線程(background=false),分別控制兩個Process類,用這兩個類分別迴圈開啟和關閉相應進程,並在前檯面板中記錄相應的資訊
比如:開啟兩個後台線程A和B,在A線程中執行個體化一個Process類Pa,在B線程中執行個體化一個Process類Pb。然後兩個線程同時進入迴圈分別做如下操作:
用Pa開啟記事本程式,並記錄記事本進程的所有可顯示資訊,然後關閉並記錄資訊,再開啟記事本程式,並記錄記事本進程的所有可顯示資訊,然後關閉並記錄資訊。。。。。。。。。。(做成死迴圈)記錄你所控制的進程的建立,運行,結束時的全部時間及PCB資訊
用Pb開啟計算機程式,並記錄記事本進程的所有可顯示資訊,然後關閉並記錄資訊,再開啟記事本程式,並記錄記事本進程的所有可顯示資訊,然後關閉並記錄資訊。。。。。。。。。。(做成死迴圈)記錄你所控制的進程的建立,運行,結束時的全部時間及PCB資訊
附:前台表單名稱為你的姓名與學號,所控制的程式不局限為記事本和計算機,在完成基本內容的基礎上對程式作出功能修改的可加分 【實驗步驟】
1.查閱MSDN中C#關於Process類和Thread類
MSDN中有Process類詳盡的解釋及屬性方法介紹,並有執行個體(Thread相對簡陋些),此處不再贅述。
Process組件提供了對運行在電腦上進程的訪問。
進程是一個啟動並執行應用程式,或者說是一個容器,應用程式運行後,就相當於將應用程式裝進容器(還可以裝載變數資料,引用的DLL檔案等)。線程是作業系統向進程分配處理器時間的基本單位。線程可執行進程的任何代碼,包括當前由另一線程執行的部分。如啟動、停止、監視應用程式等。
2.建立後台線程A, 執行個體化一個Process類Pa,迴圈開啟關閉記事本,並記錄資訊
Thread A;A = new Thread(new ThreadStart(exeNotepad)); A.IsBackground = true; A.Start();//聲明一個委託,用以解決控制項綁定到特定線程拋出的InvalidOperationException異常delegate void setRtbHandler(string s);private void setRtb(string s){ tabPage2.Controls[0].Text += s;}/// <summary>///迴圈開啟、關閉記事本程式的進程¬/// </summary>private void exeNotepad(){ Process Pa; try { int i = 1; while (true) { /開啟並關閉記事本程式 Pa = Process.Start("Notepad"); // sA= "第" + i + "次開啟記事本程式" + "\n"; sA= printProcessInfo(Pa) + "\n" + "\n"; //這裡試圖直接顯示在richTextBox上,但總是拋異常//Cross-thread operation not valid: Control 'richTextBox1' accessed from a thread //other than the thread it was//解決方案是使用委託 if (this.richTextBox1.InvokeRequired) { setRtbHandler cal = delegate(string s) { tabPage2.Controls[0].Text += sA; }; this.Invoke(cal, new object[] { sA }); //this.Invoke(new settexthandler(settext), new object[] { c.S }); } else { this.tabPage2.Controls[0].Text += sA; } Pa.Kill(); //停頓半秒 System.Threading.Thread.Sleep(1000); i++; } } catch(Exception ex) { MessageBox.Show(ex.Message); }}
3.得到進程相應資訊的函數
/// <summary>///顯示進程相關資訊的函數/// 函數中每條資訊的顯示都放在try catch語句中 /// 雖然比較冗餘,但提高互動性及顯示的規範性 /// </summary>/// <param name="process"></param>/// <returns></returns>private string printProcessInfo(Process process){ string str=""; str += "進程號:"; try{str += process.Id.ToString() + "\n";} catch(Exception ex) {str = str + ex.Message + "\n"; } str += "進程名稱:"; try{str += process.ProcessName.ToString() + "\n";} catch (Exception ex) {str = str + ex.Message + "\n";} str += "啟動時間:"; try{str += process.StartTime.ToString() + "\n";} catch (Exception ex) {str = str + ex.Message + "\n"; } str += "退出時間:"; try{str += process.ExitTime.ToString() + "\n"; str += "已耗用時間:" + (process.ExitTime - process.StartTime).ToString() + "\n";} catch (Exception ex) {str = str + ex.Message + "\n"; str += "已耗用時間:" + (DateTime.Now - process.StartTime).ToString() + "\n";} str += "進程的主模組:"; try{str += process.MainModule.ToString() + "\n";} catch (Exception ex) {str = str + ex.Message + "\n"; } str += "進程的主視窗標題:"; try{str += process.MainWindowTitle.ToString() + "\n";} catch (Exception ex) {str = str + ex.Message + "\n";} str += "進程的載入模組:"; try{str += process.Modules.ToString() + "\n";} catch (Exception ex) {str = str + ex.Message + "\n";} str += "進程的專用記憶體大小:"; try{str += Convert.ToString(process.PrivateMemorySize / 1024) + "K" + "\n";} catch (Exception ex) {str = str + ex.Message+ "\n";} str += "進程的虛擬記憶體大小:"; try{str += Convert.ToString(process.PeakVirtualMemorySize64 / 1024) + "K" + "\n";} catch (Exception ex) {str = str + ex.Message + "\n";} str += "為進程分配的分頁記憶體量:"; try{str += Convert.ToString(process.PagedMemorySize64 / 1024) + "K" + "\n";} catch (Exception ex) {str = str + ex.Message + "\n";} str += "分頁的系統記憶體大小:"; try{str += Convert.ToString(process.PagedSystemMemorySize64 / 1024) + "K" + "\n";} catch (Exception ex) {str = str + ex.Message + "\n";} str += "進程的虛擬記憶體分頁檔案最大記憶體量:"; try{str += Convert.ToString(process.PeakPagedMemorySize64 / 1024) + "K" + "\n"; } catch (Exception ex) {str = str + ex.Message + "\n";} str += "進程的允許的最大工作集大小:"; try{str += process.MaxWorkingSet.ToString() + "\n";} catch (Exception ex) {str = str + ex.Message + "\n";} str += "進程的允許的最小工作集大小:"; try{str += process.MinWorkingSet.ToString() + "\n";} catch (Exception ex) {str = str + ex.Message + "\n";} str += "進程的實體記憶體使用方式:"; try{str += Convert.ToString(process.WorkingSet / 1024) + "K" + "\n";} catch (Exception ex) {str = str + ex.Message + "\n";} str += "進程的基本優先順序:"; try{str += process.BasePriority.ToString() + "\n";} catch (Exception ex) {str = str + ex.Message + "\n";} str += "進程的總體優先順序類別:"; try{str += process.PriorityClass.ToString() + "\n";} catch (Exception ex) {str = str + ex.Message + "\n";} str += "進程的特權處理器時間:"; try{str += process.PrivilegedProcessorTime.ToString() + "\n";} catch (Exception ex) {str = str + ex.Message + "\n";} return str;}
4.同樣的方式建立線程B並執行個體化Process類Pb
5.附加功能:工作管理員類比
private void getProcessInfo() { listView1.View = View.Details; listView1.Columns.Add("映像名稱"); listView1.Columns[0].Width = 150; listView1.Columns.Add("進程ID"); listView1.Columns.Add("線程數"); listView1.Columns.Add("優先順序"); listView1.Columns.Add("實體記憶體"); listView1.Columns.Add("虛擬記憶體"); try { listView1.Items.Clear(); Process[] allProcess = Process.GetProcesses(); string[] proInfo = new string[6]; foreach(Process p in allProcess) { proInfo[0] = p.ProcessName; proInfo[1] = p.Id.ToString(); proInfo[2] = p.Threads.Count.ToString(); proInfo[3] = p.BasePriority.ToString(); proInfo[4] = Convert.ToString(p.WorkingSet / 1024) + "K"; proInfo[5] = Convert.ToString(p.VirtualMemorySize / 1024) + "K"; ListViewItem lvi = new ListViewItem(proInfo,"process"); listView1.Items.Add(lvi); } } catch(Exception ex) { MessageBox.Show(ex.Message); } }
附加功能:儲存記錄資訊
private void 儲存ToolStripMenuItem_Click(object sender, EventArgs e) { try { SaveFileDialog saveDlg = new SaveFileDialog(); saveDlg.Title = "儲存為:"; saveDlg.OverwritePrompt = true; saveDlg.Filter = "Text檔案(*.txt)|*.txt"; saveDlg.ShowHelp = true; if (saveDlg.ShowDialog() == DialogResult.OK) { string filename=saveDlg.FileName; using (StreamWriter sw = new StreamWriter(filename)) { sw.Write(this.tabPage2.Controls[0].Text); } } } catch(Exception ex) { MessageBox.Show(ex.Message); } }
【實驗截圖】
整體截圖
工作管理員截圖
【結果分析】
實驗通過使用C#中Process和Thread類嘗試了一些進程線程的基本操作。對線程和進程的概念有了更具體的瞭解
2.同時感覺C#中將Process和Thread類都封裝的比較全面,很方便就可以做很多有用的處理。比如原來還以為會“很底層”的工作管理員的“山寨版”效果,用一個Process.GetProcesses()也就出來了。另外索性嘗試了通過WMI技術進行系統管理及最佳化方面的編程,發現也很簡單。(鑒於有點跑題,報告中不多說了)
3.自己多線程編程的經驗並不多,實驗中委託的使用也是第一次嘗試。另外深刻意識到了異常處理的重要性,運行中時不時拋個異常出來,實在是讓人感覺很惱火的事兒。
4.感覺還有許多操作沒有仔細嘗試,如中斷線程Interrupt()阻止Join(),現在對基本的操作有個了大致的瞭解,等日後需要的時候再仔細研究吧。 轉載請註明出處:http://blog.csdn.net/xiaowei_cqu/article/details/7041212 程式源碼及實驗報告下載:http://download.csdn.net/detail/xiaowei_cqu/3880877