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); } }
/// <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(),现在对基本的操作有个了大致的了解,等日后需要的时候再仔细研究吧。