在實際專案開發中,資料庫連線、執行緒、大型物件等「昂貴資源」的頻繁建立與銷毀會帶來顯著的效能開銷。資源池模式透過重複使用已建立的資源實例,能有效降低系統延遲並提升吞吐量。本文介紹一個基於 C# 泛型實作的通用資源池 ResourcePool<T>,並示範如何整合至專案中。
Request() 建立新資源與 Dispose(T) 釋放資源的邏輯,讓資源池解耦具體資源建立細節。GetResource(out resourceID) 向池請求資源;池內若有閒置資源則直接返回,否則透過 IResourceProvider 建立新資源(未達上限時)。ReturnResource(ref resource, resourceID) 歸還資源,標記為可重用。以下示範如何為 SqlConnection 建立資源池,並在單元測試中驗證基本功能。
using System;
using System.Data.SqlClient;
public class SqlConnectionProvider : IResourceProvider<SqlConnection>
{
public SqlConnection Request()
{
var conn = new SqlConnection("YourConnectionStringHere");
conn.Open(); // 資源池要求管理「可用」的資源,故此處預先開啟
return conn;
}
public void Dispose(SqlConnection conn)
{
conn?.Dispose();
}
}
using NUnit.Framework;
using System.Data.SqlClient;
[TestFixture]
public class ResourcePoolTests
{
[Test]
public void TestPool_BasicUsage()
{
// 初始化資源池:提供者實例、最大資源數 10
var pool = ResourcePool<SqlConnection>.Instance(new SqlConnectionProvider(), 10);
long resourceId;
SqlConnection conn = pool.GetResource(out resourceId);
Assert.IsNotNull(conn);
Assert.IsTrue(conn.State == System.Data.ConnectionState.Open);
// 使用連線執行命令...
// using (var cmd = conn.CreateCommand()) { ... }
// 歸還資源
pool.ReturnResource(ref conn, resourceId);
Assert.IsNull(conn); // 歸還後參考應被清空
}
}
ResourcePool<T> 內部應使用鎖或無鎖佇列保護併發存取。ResourceTag 時間戳,釋放超過閒置閾值的資源。GetResource 前驗證資源可用性(如 SqlConnection.Ping),避免回傳失效連線。GetResourceAsync 以配合現代非同步程式模型。通用資源池模式將資源生命週期管理集中化,減少重複造輪子。配合 IResourceProvider 介面,即可輕鬆套用至資料庫連線、HTTP Client、大型記憶體緩衝區等場景,顯著提升系統穩定度與效能。