首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 多執行緒掃描區域網路主機列表完整實作指南

     編輯:關於C語言

前言

在區域網路管理或網路工具開發中,快速獲取 LAN 內所有活躍主機的 IP 與主機名稱是常見需求。本文提供一個基於 C# WinForms 的完整範例,採用多執行緒並行掃描 255 個 IP 位址,並透過 DNS 反向解析取得主機名稱,最後在 ListView 與 TextBox 中顯示結果,附帶進度條顯示掃描進度。

核心架構設計

  • 掃描範圍:根據本機 IP 計算同網段的 1~254 位址(例如 192.168.1.x)。
  • 多執行緒策略:為每個 IP 建立獨立執行緒(共 255 條),並行執行 Dns.GetHostEntry 反向查詢。
  • 進度回報:獨立執行緒每 100ms 更新一次 ProgressBar,模擬掃描進度。
  • 結果彙整:使用二維陣列 string[255,2] 暫存 IP 與主機名,掃描完成後一次性繫結到 UI。

關鍵程式碼解析

1. 初始化與啟動掃描

private void LanSearch()
{
    thread = new Thread[255];
    Thread threadProgress = new Thread(new ThreadStart(ProgressSearch));
    threadProgress.Start();

    string localhost = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0].ToString();
    string baseIP = localhost.Substring(0, localhost.LastIndexOf('.'));

    for (int i = 0; i < 255; i++)
    {
        int index = i; // 避免閉包捕捉變更
        ThreadStart ts = () => LanSearchThreadMethod(index, baseIP);
        thread[i] = new Thread(ts);
        thread[i].Name = i.ToString();
        thread[i].Start();
        
        // 簡易逾時控制:100ms 未完成則中止(實務建議改用 Task 與 CancellationToken)
        if (!thread[i].Join(100))
            thread[i].Abort();
    }
    GetLanHost();
    ListLanHost();
}

2. 單一 IP 掃描邏輯

private void LanSearchThreadMethod(int index, string baseIP)
{
    try
    {
        IPAddress scanIP = IPAddress.Parse($"{baseIP}.{index + 1}");
        IPHostEntry hostEntry = Dns.GetHostEntry(scanIP);
        if (hostEntry != null)
        {
            LanHost[index, 0] = scanIP.ToString();
            LanHost[index, 1] = hostEntry.HostName;
        }
    }
    catch { /* 忽略解析失敗的 IP */ }
}

3. 進度條模擬執行緒

private void ProgressSearch()
{
    for (int i = 0; i < 255; i++)
    {
        this.Invoke((Action)(() => progressBarSearch.Value = i + 1));
        Thread.Sleep(100);
    }
}

4. 結果顯示

private void ListLanHost()
{
    listView1.View = View.List;
    listView1.Items.Clear();
    for (int i = 0; i < 255; i++)
    {
        if (!string.IsNullOrEmpty(LanHost[i, 0]))
        {
            ListViewItem item = new ListViewItem(LanHost[i, 1]);
            item.Tag = LanHost[i, 0];
            listView1.Items.Add(item);
        }
    }
}

效能與架構優化建議

  1. 改用 Task Parallel Library (TPL):Parallel.For 或 Task.WhenAll 可大幅簡化程式碼,並提供更好的取消、異常處理與執行緒池管理。
  2. 非同步 DNS 查詢:.NET Core / .NET 5+ 支援 Dns.GetHostEntryAsync,避免阻塞執行緒。
  3. 限制並行數:255 條執行緒同時啟動可能造成資源耗盡,建議使用 SemaphoreSlim 或 ParallelOptions.MaxDegreeOfParallelism 限制並行數(如 50~100)。
  4. 真實進度回報:使用 Interlocked.Increment 計數已完成掃描數,配合 IProgress<T> 更新 UI,取代固定計時器。
  5. 跨執行緒 UI 操作:範例中使用 Invoke,現代寫法可搭配 async/await 與 SynchronizationContext。

完整專案結構提醒

  • 表單需包含:TextBox (多行)、Button、ProgressBar、ListView (含兩欄 ColumnHeader)。
  • 命名空間:System.Net, System.Threading, System.Windows.Forms。
  • 記得在 FormClosing 中正確釋放執行緒資源,避免程式關閉時殘留執行緒。

總結

本範例展示了傳統 Thread 類別實作 LAN 掃描的基本原理。雖然程式碼可執行,但現代開發強烈建議改用 Task/async-await 模式,配合 Parallel.ForEach 或 SemaphoreSlim 控制並行度,能獲得更佳的效能、穩定度與可維護性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved