這個資源池用來管理程序的寶貴資源。
主要的類是ResourcePool<T>。
用戶可以通過調用GetResource方法請求一個資源,用完之後通過ReturnResource歸還給資源池。由資源池決定什麼時候釋放多余的資源。
接口IResourceProvider<T>用來獲得資源。
類ResourceTag<T>用來標志資源是否在用。
具體的就不多說了,請看代碼。歡迎討論。
先是測試代碼:
1 using System;
2 using NUnit.Framework;
3 using System.Data.SqlClient;
4 public class SqlConnectionProvider: IResourceProvider<SqlConnection>
5 {
6 public SqlConnection Request()
7 {
8 SqlConnection con= new SqlConnection();
9 //在此打開數據庫連接,因為ResourcePool要求管理那些能用的資源。
10 //con.Open();
11 return con;
12 }
13 public void Dispose(SqlConnection con)
14 {
15 //在此銷毀對象
16 con.Dispose();
17 }
18 }
19 [TestFixture]
20 public class Test
21 {
22 [Test]
23 public void TestPool()
24 {
25 //此處初始化資源池,參數:一個資源提供類和一個最大資源池中最大資源數目
26 ResourcePool<SqlConnection> pool=ResourcePool<SqlConnection>.Instance(new SqlConnectionProvider(),10);
27
28 long resourceID;
29 SqlConnection con=pool.GetResource(out resourceID);
30 //在此處使用con對象
31
32 //用完就歸還
33 pool.ReturnResource(ref con,resourceID);
34
35
36 }
37 }
(以上測試只是簡單的演示功能,詳細的測試代碼跟項目其他類有關,貼上反而復雜)
具體實現:
1 /// <summary>
2 /// 資源池,可以往裡面加入資源,也可以取出來
3 /// </summary>
4 /// <typeparam name="T"></typeparam>
5 public class ResourcePool<T> : IDisposable where T : class, IDisposable
6 {
7 private static ResourcePool<T> pool;
8 IResourceProvider<T> resourceProvider;
9 static int maxResource;
10
11 public static int MaxResource
12 {
13 get { return ResourcePool<T>.maxResource; }
14
15 }
16 private ResourcePool(IResourceProvider<T> resourceProvider, int maxResource)
17 {
18 this.resourceProvider = resourceProvider;
19 ResourcePool<T>.maxResource = maxResource;
20 resources = new Dictionary<long,ResourceTag<T>> ();
21 }
22 public int ResourceCount
23 {
24 get
25 {
26 return resources.Keys.Count;
27 }
28 }
29
30 static object key3 = new object();
31 /// <summary>
32 /// 返回一個資源池,采用單件模式。
33 /// </summary>
34 /// <param name="resourceProvider"></param>
35 /// <returns></returns>
36 public static ResourcePool<T> Instance(IResourceProvider<T> resourceProvider, int maxResource)
37 {
38 if (pool == null)
39 {
40 lock (key3)
41 {
42 if (pool == null)
43 {
44 pool = new ResourcePool<T>(resourceProvider, maxResource);
45 }
46 }
47 }
48 return pool;
49 }
50 Dictionary<long,ResourceTag<T>> resources;
51 /// <summary>
52 ///從資源池中提取資源
53 /// </summary>
54 /// <param name="resourID">向資源用戶輸出的resourceID,返回資源時用它來返回特定資源</param>
55 /// <returns></returns>
56 public T GetResource(out long resourID)
57 {
58 T result = null;
59 result = getFreeResource(out resourID);
60 return result;
61 }
62 object key1 = new object();
63 private T getFreeResource(out long resourID)
64 {
65 lock (key1)
66 {
67 foreach (long key in resources.Keys)
68 {
69 if (!resources[key].InUse)
70 {
71 resources[key].InUse = true;
72 resourID = key;
73 return resources[key].Resource;
74 }
75 }
76 //申請新資源
77 T res = resourceProvider.Request();
78 if (res == null)//申請資源失敗
79 {
80 resourID = getNullResourceID();
81 return null;
82 }
83 else
84 {
85 ResourceTag<T> tag = new ResourceTag<T>(res, true);
86 long id = newResourceID();
87 resources.Add(id, tag);
88 resourID=id;
89 return res;
90 }
91 }
92 }
93
94 private long getNullResourceID()
95 {
96 return -1;
97 }
98 /// <summary>
99 /// 產生新的資源號
100 /// </summary>
101 /// <returns></returns>
102 private long newResourceID()
103 {
104 return DateTime.Now.Ticks;
105 }
106
107
108 /// <summary>
109 /// 返回資源
110 /// </summary>
111 /// <param name="resource">ref類型的參數,將在函數內部設為null,意味著返回後不能再用。</param>
112 /// <param name="resourceID">獲取資源時得到的那個resourceID。如果返回一個不正確的id,將拋出異常。</param>
113 public void ReturnResource(ref T resource, long resourceID)
114 {
115 if (!resources.ContainsKey(resourceID))
116 {
117 throw new InvalidOperationException("試圖歸還一個非法的資源。");
118 }
119 returnRes(ref resource,resourceID);
120 }
121 object key2 = new object();
122 private void returnRes(ref T resource, long resourceID)
123 {
124 T toDispose = null;
125 lock (key2)
126 {
127 ResourceTag<T> tag = resources[resourceID];
128 tag.InUse = false;
129 resources.Remove(resourceID);//當前的id將作廢,不能再用
130 resource = null;//將當前的resource置空,不能再用
131 if (resources.Keys.Count >= maxResource)//達到上限,將釋放資源
132 {
133 toDispose = resource;
134 }
135 else
136 {
137 resources.Add(newResourceID(), tag);
138 }
139 }
140 if (toDispose != null)
141 {
142 resourceProvider.Dispose(toDispose);
143 }
144 }
145 #region IDisposable 成員 及 析構方法
146
147 public void Dispose()
148 {
149 Dispose(true);
150 }
151 ~ResourcePool()
152 {
153 Dispose(false);
154 }
155 public virtual void Dispose(bool isDisposing)
156 {
157 foreach (long key in resources.Keys)
158 {
159 resources[key].Resource.Dispose();//釋放資源
160 }
161 if (isDisposing)
162 {
163 key1 = null;
164 key2 = null;
165 key3 = null;
166 resourceProvider = null;
167 }
168 }
169 #endregion
170
171 }
172 internal class ResourceTag<T>
173 {
174 private T resource;
175
176 internal T Resource
177 {
178 get { return resource; }
179 set { resource = value; }
180 }
181 private bool inUse;
182
183 internal bool InUse
184 {
185 get { return inUse; }
186 set { inUse = value; }
187 }
188 public ResourceTag(T resource, bool inUse)
189 {
190 Resource = resource;
191 InUse = inUse;
192 }
193
194 }
195 /// <summary>
196 /// 這個接口用來產生ResourcePool管理的資源,比如數據庫連接對象等
197 /// </summary>
198 /// <typeparam name="T"></typeparam>
199 public interface IResourceProvider<T> where T : class, IDisposable
200 {
201 /// <summary>
202 /// 獲得資源
203 /// </summary>
204 /// <returns>成功則返回資源對象,否則返回null</returns>
205 T Request();
206 void Dispose(T resource);
207 }