重構前須解決的兩大問題
- 執行緒無回傳值:
ThreadStart 委派指向 void Method(),需將掃描邏輯封裝為無回傳程序。
- 跨執行緒傳遞結果:掃描結果 (IP、主機名) 需回報主執行緒更新 UI,解決方案:**委派回呼模式**。
具體重構步驟
1. 引入命名空間
using System.Threading;
2. 定義回呼委派 (Namespace 層級)
public delegate void UpdateList(string ip, string hostName);
3. 表單層級變數:記錄開始時間
private DateTime startTime;
4. 封裝掃描邏輯類別:PingScanner
public class PingScanner
{
public UpdateList UpdateCallback; // 委派參考
public string IP; // 目標 IP
public string HostName; // 掃描結果
public void Scan()
{
IPAddress ipAddr = IPAddress.Parse(IP);
try
{
IPHostEntry host = Dns.GetHostEntry(ipAddr);
HostName = host.HostName;
}
catch { HostName = ""; }
if (string.IsNullOrEmpty(HostName))
HostName = " 主機沒有響應!";
// 執行回呼 (若已指派)
UpdateCallback?.Invoke(IP, HostName);
}
}
5. 表單實作回呼方法:UpdateMyList
void UpdateMyList(string ip, string hostName)
{
lock (listBox1) // 確保執行緒安全
{
listBox1.Items.Add(ip + " " + hostName);
if (progressBar1.Value != progressBar1.Maximum)
progressBar1.Value++;
if (progressBar1.Value == progressBar1.Maximum)
{
MessageBox.Show("掃描完成!");
TimeSpan elapsed = DateTime.Now - startTime;
label4.Text = elapsed.Seconds + " 秒";
progressBar1.Value = progressBar1.Minimum;
}
}
}
架構優勢
- 關注點分離:掃描邏輯 (PingScanner) 與 UI 更新 (UpdateMyList) 解耦
- 執行緒安全:
lock 保護共享 UI 控制項
- 擴充性:未來可輕鬆換成
ThreadPool.QueueUserWorkItem 或 Task.Run