这个资源池用来管理程序的宝贵资源。
主要的类是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         private ResourcePool(IResourceProvider<T> resourceProvider)
 10         {
 11             this.resourceProvider = resourceProvider;
 12             resources = new Dictionary<long,ResourceTag<T>> ();
 13         }
 14         public int ResourceCount
 15         {
 16             get
 17             {
 18                 return resources.Keys.Count;
 19             }
 20         }
 21 
 22         static object key3 = new object();
 23         /// <summary>
 24         /// 返回一个资源池,采用单件模式。
 25         /// </summary>
 26         /// <param name="resourceProvider"></param>
 27         /// <returns></returns>
 28         public static  ResourcePool<T> Instance(IResourceProvider<T> resourceProvider)
 29         {
 30             if (pool == null)
 31             {
 32                 lock (key3)
 33                 {
 34                     if (pool == null)
 35                     {
 36                         pool = new ResourcePool<T>(resourceProvider);
 37                     }
 38                 }
 39             }
 40             return pool;
 41         }
 42         Dictionary<long,ResourceTag<T>> resources;
 43         /// <summary>
 44         ///从资源池中提取资源
 45         /// </summary>
 46         /// <param name="resourID">向资源用户输出的resourceID,返回资源时用它来返回特定资源</param>
 47         /// <returns></returns>
 48         public T GetResource(out long resourID)
 49         {
 50             T result = null;
 51             result = getFreeResource(out resourID);
 52             return result;
 53         }
 54         object key1 = new object();
 55         private T getFreeResource(out long resourID)
 56         {
 57             lock (key1)
 58             {
 59                 foreach (long key in resources.Keys)
 60                 {
 61                     if (!resources[key].InUse)
 62                     {
 63                         resources[key].InUse = true;
 64                         resourID = key;
 65                         return resources[key].Resource;
 66                     }
 67                 }
 68                 //申请新资源
 69                 T res = resourceProvider.Request();
 70                 if (res == null)//申请资源失败
 71                 {
 72                     resourID = getNullResourceID();
 73                     return null;
 74                 }
 75                 else
 76                 {
 77                     ResourceTag<T> tag = new ResourceTag<T>(res, true);
 78                     long id = newResourceID();
 79                     resources.Add(id, tag);
 80                     resourID=id;
 81                     return res;
 82                 }
 83             }
 84         }
 85 
 86         private long getNullResourceID()
 87         {
 88             return -1;
 89         }
 90         /// <summary>
 91         /// 产生新的资源号
 92         /// </summary>
 93         /// <returns></returns>
 94         private long newResourceID()
 95         {
 96             return DateTime.Now.Ticks;
 97         }
 98 
 99 
100         /// <summary>
101         /// 返回资源
102         /// </summary>
103         /// <param name="resource">ref类型的参数,将在函数内部设为null,意味着返回后不能再用。</param>
104         /// <param name="resourceID">获取资源时得到的那个resourceID。如果返回一个不正确的id,将抛出异常。</param>
105         public void ReturnResource(ref T resource, long resourceID)
106         {
107             if (!resources.ContainsKey(resourceID))
108             {
109                 throw new InvalidOperationException("试图归还一个非法的资源。");
110             }
111             returnRes(ref resource,resourceID);
112         }
113         object key2 = new object();
114         private void returnRes(ref T  resource, long resourceID)
115         {
116             T toDispose = null;
117             lock (key2)
118             {
119                 ResourceTag<T> tag = resources[resourceID];
120                 tag.InUse = false;
121                 resources.Remove(resourceID);//当前的id将作废,不能再用
122                 resource = null;//将当前的resource置空,不能再用
123                 if (resources.Keys.Count >=resourceProvider.MaxResource)//达到上限,将释放资源
124                 {
125                     toDispose = resource;
126                 }
127                 else
128                 {
129                     resources.Add(newResourceID(), tag);
130                 }
131             }
132             if (toDispose != null)
133             {
134                 resourceProvider.Dispose(toDispose);
135             }
136         }
137         #region IDisposable 成员 及 析构方法
138 
139         public void Dispose()
140         {
141             Dispose(true);
142         }
143         ~ResourcePool()
144         {
145             Dispose(false);
146         }
147         public virtual void Dispose(bool isDisposing)
148         {
149             foreach (long key in resources.Keys)
150             {
151                 resources[key].Resource.Dispose();//释放资源
152             }
153             if (isDisposing)
154             {
155                 key1 = null;
156                 key2 = null;
157                 key3 = null;
158                 resourceProvider = null;GC.SuppressFinalize()
159             }
160         }
161         #endregion
162 
163     }
164     internal class ResourceTag<T>
165     {
166         private T resource;
167 
168         internal T Resource
169         {
170             get { return resource; }
171             set { resource = value; }
172         }
173         private bool inUse;
174 
175         internal bool InUse
176         {
177             get { return inUse; }
178             set { inUse = value; }
179         }
180         public ResourceTag(T resource, bool inUse)
181         {
182             Resource = resource;
183             InUse = inUse;
184         }
185 
186     }
187     /// <summary>
188     /// 这个接口用来产生ResourcePool管理的资源,比如数据库连接对象等
189     /// </summary>
190     /// <typeparam name="T"></typeparam>
191     public interface IResourceProvider<T> where T : class, IDisposable
192     {
193         /// <summary>
194         /// 获得资源
195         /// </summary>
196         /// <returns>成功则返回资源对象,否则返回null</returns>
197         T Request();
198         void Dispose(T resource);
199         /// <summary>
200         /// 能提供的最大的资源数
201         /// </summary>
202         int MaxResource { get;}
203     }

 

posted on 2009-03-20 18:38  apple123  阅读(3039)  评论(8编辑  收藏  举报