今天重新學習了一下觀察者模式,對我的思路產生了啟發。進程監控程序之前寫過幾個,這回換一種思路,改用委托和事件來實現。我已經用序號將關鍵的幾步標注,方便大家理順思路。代碼如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace ProcessMonitor { public partial class ProcessMonitorForm : Form { public ProcessMonitorForm() { InitializeComponent(); //Add the processes into the combox. var processes = Process.GetProcesses(); foreach (var process in processes) { processComboBox.Items.Add(process.ProcessName.ToString()); } } //The method that starts the monitor. private void startButton_Click(object sender, EventArgs e) { //4.Register the monitor. ProcessExit += new ProcessMonitor(ProExit); //Start the check. CheckProcess(); } //The mothod that checks the process. private void CheckProcess() { bool flag = true; do { var processes = Process.GetProcesses(); int count = 0; foreach (var process in processes) { if (string.Compare(process.ProcessName, processComboBox.Text, true) == 0) { count++; } } if (count == 0) { //5.The event appears. ProcessExit(this, new EventArgs()); flag = false; } } while (flag); } //1.The delegate that monitor the process. public delegate void ProcessMonitor(object sender, EventArgs strEventArg); //2.The event that encapsulates the delegate. public event ProcessMonitor ProcessExit; //3.The method that the delegate calls. private void ProExit(object sender, EventArgs strEventArg) { MessageBox.Show("The target process has been dispeared."); } } }
為了不長篇累牘,效果只是簡單實現,實際工作中可以隨便擴展(選擇進程,點擊Start按鈕進行監控。):
目標程序消失后彈出提示:
再附上一個脫去委托和事件的版本,代碼如下(實現效果相同):
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace ProcessMonitor { public partial class ProcessMonitorForm : Form { public ProcessMonitorForm() { InitializeComponent(); //Add the processes into the combox. var processes = Process.GetProcesses(); foreach (var process in processes) { processComboBox.Items.Add(process.ProcessName.ToString()); } } //The method that starts the monitor. private void startButton_Click(object sender, EventArgs e) { //Start the check. CheckProcess(); } //The mothod that checks the process. private void CheckProcess() { bool flag = true; do { var processes = Process.GetProcesses(); int count = 0; foreach (var process in processes) { if (string.Compare(process.ProcessName, processComboBox.Text, true) == 0) { count++; } } if (count == 0) { ProExit(); flag = false; } } while (flag); } private void ProExit() { MessageBox.Show("The target process has been dispeared."); } } }
如果用Action內置委托類型來完成的話就更方便了,代碼如下(已經用序號標注關鍵步驟):
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace ProcessMonitor { public partial class ProcessMonitorForm : Form { public ProcessMonitorForm() { InitializeComponent(); //Add the processes into the combox. var processes = Process.GetProcesses(); foreach (var process in processes) { processComboBox.Items.Add(process.ProcessName.ToString()); } } //The method that starts the monitor. private void startButton_Click(object sender, EventArgs e) { //Start the check. CheckProcess(); } //The mothod that checks the process. private void CheckProcess() { //1.Define the action. Action<string> processExit = s => MessageBox.Show(s); bool flag = true; do { var processes = Process.GetProcesses(); int count = 0; foreach (var process in processes) { if (string.Compare(process.ProcessName, processComboBox.Text, true) == 0) { count++; } } if (count == 0) { //2.Active the action. processExit("The target process has been dispeared."); flag = false; } } while (flag); } } }
脫去委托和事件的版本代碼量明顯比用委托和事件的代碼量少了,為什么我們還要選擇用委托和事件來做這件事呢?到底什么情況下,更適合用委托和事件的方式來完成?書中說,委托可以提高方法擴展性,沒錯,是這樣的,說白了就是因為更高級!個人意見哈,在代碼量少,以后不需要擴展方法的情況下,用不着用委托和事件的方式去完成,直接調用方法就好了。如果我說錯了,歡迎指正我。
利用C#6.0中的語法糖擴展方法來替代foreach循環,代碼量將更少。代碼如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace ProcessMonitor { public partial class ProcessMonitorForm : Form { public ProcessMonitorForm() { InitializeComponent(); //Add the processes into the combox. var processes = Process.GetProcesses(); foreach (var process in processes) { processComboBox.Items.Add(process.ProcessName.ToString()); } } //The method that starts the monitor. private void startButton_Click(object sender, EventArgs e) { //Start the check. CheckProcess(); } //The mothod that checks the process. private void CheckProcess() { //1.Define the action. Action<string> processExit = s => MessageBox.Show(s); bool flag = true; do { var processes = Process.GetProcesses(); var countVar = processes.Where(i => i.ProcessName == processComboBox.Text); if (countVar.Count() == 0) { //2.Active the action. processExit("The target process has been dispeared."); flag = false; } } while (flag); } } }