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

Socket 網路程式設計學習筆記 (6):使用執行緒池提升效能 (完結篇)

     編輯:關於.NET

前言

前幾篇介紹的伺服器端監聽與客戶端連接,皆採「每連接一執行緒」模式:new Thread(...).Start()。頻繁建立/銷毀執行緒帶來顯著開銷。.NET 提供 ThreadPool 解決此問題,本文示範如何套用至 Socket 通訊。

執行緒池基礎

  • Windows 維護「預先建立」的執行緒池供應用程式派遣工作
  • 單一執行緒控制池操作,應用程式可配置額外執行緒
  • 預設 25 個背景執行緒,滿足中小型應用
  • 排入佇列即執行,無需呼叫 Start()
  • 主執行緒結束時,所有池執行緒自動終止(不等待)

核心 API

ThreadPool.QueueUserWorkItem(new WaitCallback(CallbackMethod));
  • QueueUserWorkItem:靜態方法,將工作項目排入佇列
  • WaitCallback:委派簽名 void Method(object state),必須接受一個 object 參數

改造前後對比

原版:手動建立執行緒

clientThread = new Thread(new ThreadStart(ReceiveData));
clientThread.Start();

新版:執行緒池

ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveData));

只需一行,且 ReceiveData 簽名需調整為 void ReceiveData(object state)。

完整範例架構

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;

public class TcpServer
{
    private TcpListener _listener;
    private bool _running;

    public void Start(int port)
    {
        _listener = new TcpListener(IPAddress.Any, port);
        _listener.Start();
        _running = true;
        
        // 監聽迴圈也可用執行緒池
        ThreadPool.QueueUserWorkItem(ListenLoop);
    }

    private void ListenLoop(object state)
    {
        while (_running)
        {
            try
            {
                TcpClient client = _listener.AcceptTcpClient();
                // 每個客戶端連接派遣到執行緒池處理
                ThreadPool.QueueUserWorkItem(HandleClient, client);
            }
            catch (SocketException)
            {
                // 監聽停止等
            }
        }
    }

    private void HandleClient(object state)
    {
        TcpClient client = (TcpClient)state;
        NetworkStream stream = client.GetStream();
        
        try
        {
            // 收發邏輯...
            byte[] buffer = new byte[1024];
            int bytesRead = stream.Read(buffer, 0, buffer.Length);
            // 處理資料...
            
            // 回應
            byte[] response = System.Text.Encoding.ASCII.GetBytes("OK");
            stream.Write(response, 0, response.Length);
        }
        finally
        {
            client.Close();
        }
    }

    public void Stop()
    {
        _running = false;
        _listener.Stop();
    }
}

效能優勢分析

指標手動執行緒執行緒池
建立開銷高 (核心物件配置、堆疊空間)低 (重用既有執行緒)
記憶體壓力每執行緒 1MB 預設堆疊固定池大小
延遲需建立後啟動排入即執行
資源控制難以限制最大並發ThreadPool.SetMaxThreads 可控制

注意事項

  • 避免長時間阻塞:池執行緒應快速完成工作,長時間運算請用 Task.Run 或自建執行緒
  • 例外處理:工作項目內未捕獲的例外會終止進程 (.NET 2.0+)
  • 非同步替代方案:.NET 4.5+ 建議使用 async/await + SocketAsyncEventArgs 或 NetworkStream.ReadAsync,比執行緒池更具擴展性

系列總結

六篇筆記涵蓋:

  1. 常用網路類別 (IPAddress, IPEndPoint, Dns)
  2. TCP Socket 基礎通訊
  3. TcpListener/TcpClient 助手類別
  4. 訊息邊界處理 (固定長度、長度前綴、分隔符)
  5. 實體物件序列化傳輸 (SOAP/Binary/Xml)
  6. 執行緒池優化 (本篇)

原始碼下載:本文配套原始碼

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