Pool.cs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Data;
  5. using System.Data.SqlClient;
  6. using System.Data.Common;
  7. using System.Threading;
  8. using System.Collections;
  9. namespace DateBaseConnectionPool
  10. {
  11. /// <summary>
  12. /// 数据库连接池,默认数据库连接方案是ODBC
  13. /// </summary>
  14. public class Pool : IDisposable
  15. {
  16. #region 变量定义
  17. //属性
  18. private int _realFormPool;//连接池中存在的实际连接数(包含失效的连接)
  19. private int _potentRealFormPool;//连接池中存在的实际连接数(有效的实际连接)
  20. private int _spareRealFormPool;//空闲的实际连接
  21. private int _useRealFormPool;//已分配的实际连接
  22. private int _readOnlyFormPool;//连接池已经分配多少只读连接
  23. private int _useFormPool;//已经分配出去的连接数
  24. private int _spareFormPool;//目前可以提供的连接数
  25. private int _maxConnection;//最大连接数,最大可以创建的连接数目
  26. private int _minConnection;//最小连接数
  27. private int _seepConnection;//每次创建连接的连接数
  28. private int _keepRealConnection;//保留的实际空闲连接,以攻可能出现的ReadOnly使用,当空闲连接不足该数值时,连接池将创建seepConnection个连接
  29. private int _exist = 20;//每个连接生存期限 20分钟
  30. private int _maxRepeatDegree = 5;//可以被重复使用次数(引用记数),当连接被重复分配该值所表示的次数时,该连接将不能被分配出去
  31. //当连接池的连接被分配尽时,连接池会在已经分配出去的连接中,重复分配连接(引用记数)。来缓解连接池压力
  32. private DateTime _startTime;//服务启动时间
  33. private string _connString = null;//连接字符串
  34. private ConnTypeEnum _connType;//连接池连接类型
  35. private PoolState _ps;//连接池状态
  36. //内部对象
  37. private List<ConnStruct> al_All = new List<ConnStruct>();//实际连接
  38. private Hashtable hs_UseConn = new Hashtable();//正在使用的连接
  39. private System.Timers.Timer time;//监视器记时器
  40. private Thread threadCreate;//创建线程
  41. private bool isThreadCheckRun = false;
  42. //private Mutex mUnique = new Mutex();
  43. #endregion
  44. //--------------------------------------------------------------------
  45. #region 构造方法 与 初始化函数
  46. /// <summary>
  47. /// 初始化连接池
  48. /// </summary>
  49. /// <param name="connectionString">数据库连接字符串</param>
  50. public Pool(string connectionString)
  51. { InitConnectionPool(connectionString, ConnTypeEnum.Odbc, 200, 30, 10, 5, 5); }
  52. /// <summary>
  53. /// 初始化连接池
  54. /// </summary>
  55. /// <param name="connectionString">数据库连接字符串</param>
  56. /// <param name="cte">数据库连接类型</param>
  57. public Pool(string connectionString, ConnTypeEnum cte)
  58. { InitConnectionPool(connectionString, cte, 200, 30, 10, 5, 5); }
  59. /// <summary>
  60. /// 初始化连接池
  61. /// </summary>
  62. /// <param name="connectionString">数据库连接字符串</param>
  63. /// <param name="cte">数据库连接类型</param>
  64. /// <param name="maxConnection">最大连接数,最大可以创建的连接数目</param>
  65. /// <param name="minConnection">最小连接数</param>
  66. public Pool(string connectionString, ConnTypeEnum cte, int maxConnection, int minConnection)
  67. { InitConnectionPool(connectionString, cte, maxConnection, minConnection, 10, 5, 5); }
  68. /// <summary>
  69. /// 初始化连接池
  70. /// </summary>
  71. /// <param name="connectionString">数据库连接字符串</param>
  72. /// <param name="cte">数据库连接类型</param>
  73. /// <param name="maxConnection">最大连接数,最大可以创建的连接数目</param>
  74. /// <param name="minConnection">最小连接数</param>
  75. /// <param name="seepConnection">每次创建连接的连接数</param>
  76. /// <param name="keepConnection">保留连接数,当空闲连接不足该数值时,连接池将创建seepConnection个连接</param>
  77. public Pool(string connectionString, ConnTypeEnum cte, int maxConnection, int minConnection, int seepConnection, int keepConnection)
  78. { InitConnectionPool(connectionString, cte, maxConnection, minConnection, seepConnection, keepConnection, 5); }
  79. /// <summary>
  80. /// 初始化连接池
  81. /// </summary>
  82. /// <param name="connectionString">数据库连接字符串</param>
  83. /// <param name="cte">数据库连接类型</param>
  84. /// <param name="maxConnection">最大连接数,最大可以创建的连接数目</param>
  85. /// <param name="minConnection">最小连接数</param>
  86. /// <param name="seepConnection">每次创建连接的连接数</param>
  87. /// <param name="keepConnection">保留连接数,当空闲连接不足该数值时,连接池将创建seepConnection个连接</param>
  88. /// <param name="keepRealConnection">当空闲的实际连接不足该值时创建连接,直到达到最大连接数</param>
  89. public Pool(string connectionString, ConnTypeEnum cte, int maxConnection, int minConnection, int seepConnection, int keepConnection, int keepRealConnection)
  90. { InitConnectionPool(connectionString, cte, maxConnection, minConnection, seepConnection, keepConnection, keepRealConnection); }
  91. /// <summary>
  92. /// 初始化函数
  93. /// </summary>
  94. protected void InitConnectionPool(string connectionString, ConnTypeEnum cte, int maxConnection, int minConnection, int seepConnection, int keepConnection, int keepRealConnection)
  95. {
  96. if (cte == ConnTypeEnum.None)
  97. throw new ConnTypeExecption();//参数不能是None
  98. _ps = PoolState.UnInitialize;
  99. this._connString = connectionString;
  100. this._connType = cte;
  101. this._minConnection = minConnection;
  102. this._seepConnection = seepConnection;
  103. this._keepRealConnection = keepRealConnection;
  104. this._maxConnection = maxConnection;
  105. this.time = new System.Timers.Timer(500);
  106. this.time.Stop();
  107. this.time.Elapsed += new System.Timers.ElapsedEventHandler(time_Elapsed);
  108. this.threadCreate = new Thread(new ThreadStart(createThreadProcess));
  109. }
  110. #endregion
  111. //--------------------------------------------------------------------
  112. #region 属性部分
  113. /// <summary>
  114. /// 连接池服务状态
  115. /// </summary>
  116. public PoolState State
  117. { get { return _ps; } }
  118. /// <summary>
  119. /// 连接池是否启动,改变该属性将相当于调用StartServices或StopServices方法,注:只有连接池处于Run,Stop状态情况下才可以对此属性赋值
  120. /// </summary>
  121. public bool Enable
  122. {
  123. get
  124. {
  125. if (_ps == PoolState.Run)
  126. return true;
  127. else
  128. return false;
  129. }
  130. set
  131. {
  132. if (_ps == PoolState.Run || _ps == PoolState.Stop)
  133. if (value == true)
  134. StartServices();
  135. else
  136. StopServices();
  137. else
  138. throw new SetValueExecption();//只有连接池处于Run,Stop状态情况下才可以对此属性赋值
  139. }
  140. }
  141. /// <summary>
  142. /// 得到或设置连接类型
  143. /// </summary>
  144. public ConnTypeEnum ConnectionType
  145. {
  146. get { return _connType; }
  147. set
  148. {
  149. if (_ps == PoolState.Stop)
  150. _connType = value;
  151. else
  152. throw new SetValueExecption();//只有在Stop状态时才可操作
  153. }
  154. }
  155. /// <summary>
  156. /// 连接池使用的连接字符串
  157. /// </summary>
  158. public string ConnectionString
  159. {
  160. get { return _connString; }
  161. set
  162. {
  163. if (_ps == PoolState.Stop)
  164. _connString = value;
  165. else
  166. throw new SetValueExecption();//只有在Stop状态时才可操作
  167. }
  168. }
  169. /// <summary>
  170. /// 得到服务器运行时间
  171. /// </summary>
  172. public DateTime RunTime
  173. {
  174. get
  175. {
  176. if (_ps == PoolState.Stop)
  177. return new DateTime(DateTime.Now.Ticks - _startTime.Ticks);
  178. else
  179. return new DateTime(0);
  180. }
  181. }
  182. /// <summary>
  183. /// 最小连接数
  184. /// </summary>
  185. public int MinConnection
  186. {
  187. get { return _minConnection; }
  188. set
  189. {
  190. if (value < _maxConnection && value > 0 && value >= _keepRealConnection)
  191. _minConnection = value;
  192. else
  193. throw new ParameterBoundExecption();//参数范围应该在 0~MaxConnection之间,并且应该大于KeepConnection
  194. }
  195. }
  196. /// <summary>
  197. /// 最大连接数,最大可以创建的连接数目
  198. /// </summary>
  199. public int MaxConnection
  200. {
  201. get { return _maxConnection; }
  202. set
  203. {
  204. if (value >= _minConnection && value > 0)
  205. _maxConnection = value;
  206. else
  207. throw new ParameterBoundExecption();//参数范围错误,参数应该大于minConnection
  208. }
  209. }
  210. /// <summary>
  211. /// 每次创建连接的连接数
  212. /// </summary>
  213. public int SeepConnection
  214. {
  215. get { return _seepConnection; }
  216. set
  217. {
  218. if (value > 0 && value < _maxConnection)
  219. _seepConnection = value;
  220. else
  221. throw new ParameterBoundExecption();//创建连接的步长应大于0,同时小于MaxConnection
  222. }
  223. }
  224. /// <summary>
  225. /// 保留的实际空闲连接,以攻可能出现的ReadOnly使用
  226. /// </summary>
  227. public int KeepRealConnection
  228. {
  229. get { return _keepRealConnection; }
  230. set
  231. {
  232. if (value >= 0 && value < _maxConnection)
  233. _keepRealConnection = value;
  234. else
  235. throw new ParameterBoundExecption();//保留连接数应大于等于0,同时小于MaxConnection
  236. }
  237. }
  238. /// <summary>
  239. /// 自动清理连接池的时间间隔
  240. /// </summary>
  241. public double Interval
  242. {
  243. get { return time.Interval; }
  244. set { time.Interval = value; }
  245. }
  246. /// <summary>
  247. /// 每个连接生存期限(单位分钟),默认20分钟
  248. /// </summary>
  249. public int Exist
  250. {
  251. get { return _exist; }
  252. set
  253. {
  254. if (_ps == PoolState.Stop)
  255. _exist = value;
  256. else
  257. throw new PoolNotStopException();//只有在Stop状态下才可以操作
  258. }
  259. }
  260. /// <summary>
  261. /// 可以被重复使用次数(引用记数)当连接被重复分配该值所表示的次数时,该连接将不能被分配出去。
  262. /// 当连接池的连接被分配尽时,连接池会在已经分配出去的连接中,重复分配连接(引用记数)。来缓解连接池压力
  263. /// </summary>
  264. public int MaxRepeatDegree
  265. {
  266. get { return _maxRepeatDegree; }
  267. set
  268. {
  269. if (value >= 0)
  270. _maxRepeatDegree = value;
  271. else
  272. throw new ParameterBoundExecption();//重复引用次数应大于等于0
  273. }
  274. }
  275. /// <summary>
  276. /// 连接池最多可以提供多少个连接
  277. /// </summary>
  278. public int MaxConnectionFormPool
  279. { get { return _maxConnection * _maxRepeatDegree; } }
  280. /// <summary>
  281. /// 连接池中存在的实际连接数(有效的实际连接)
  282. /// </summary>
  283. public int PotentRealFormPool
  284. {
  285. get
  286. {
  287. if (_ps == PoolState.Run)
  288. return _potentRealFormPool;
  289. else
  290. throw new PoolNotRunException();//连接池处在非运行中
  291. }
  292. }
  293. /// <summary>
  294. /// 连接池中存在的实际连接数(包含失效的连接)
  295. /// </summary>
  296. public int RealFormPool
  297. {
  298. get
  299. {
  300. if (_ps == PoolState.Run)
  301. return _realFormPool;
  302. else
  303. throw new PoolNotRunException();//连接池处在非运行中
  304. }
  305. }
  306. /// <summary>
  307. /// 空闲的实际连接
  308. /// </summary>
  309. public int SpareRealFormPool
  310. {
  311. get
  312. {
  313. if (_ps == PoolState.Run)
  314. return _spareRealFormPool;
  315. else
  316. throw new PoolNotRunException();//连接池处在非运行中
  317. }
  318. }
  319. /// <summary>
  320. /// 已分配的实际连接
  321. /// </summary>
  322. public int UseRealFormPool
  323. {
  324. get
  325. {
  326. if (_ps == PoolState.Run)
  327. return _useRealFormPool;
  328. else
  329. throw new PoolNotRunException();//连接池处在非运行中
  330. }
  331. }
  332. /// <summary>
  333. /// 连接池已经分配多少只读连接
  334. /// </summary>
  335. public int ReadOnlyFormPool
  336. {
  337. get
  338. {
  339. if (_ps == PoolState.Run)
  340. return _readOnlyFormPool;
  341. else
  342. throw new PoolNotRunException();//连接池处在非运行中
  343. }
  344. }
  345. /// <summary>
  346. /// 已经分配的连接数
  347. /// </summary>
  348. public int UseFormPool
  349. {
  350. get
  351. {
  352. if (_ps == PoolState.Run)
  353. return _useFormPool;
  354. else
  355. throw new PoolNotRunException();//连接池处在非运行中
  356. }
  357. }
  358. /// <summary>
  359. /// 目前可以提供的连接数
  360. /// </summary>
  361. public int SpareFormPool
  362. {
  363. get
  364. {
  365. if (_ps == PoolState.Run)
  366. return _spareFormPool;
  367. else
  368. throw new PoolNotRunException();//连接池处在非运行中
  369. }
  370. }
  371. #endregion
  372. //--------------------------------------------------------------------
  373. #region 启动服务 与 终止服务
  374. /// <summary>
  375. /// 启动服务,线程安全,同步调用
  376. /// </summary>
  377. public void StartServices()
  378. { StartServices(false); }
  379. /// <summary>
  380. /// 启动服务,线程安全
  381. /// </summary>
  382. /// <param name="ansy">是否异步调用True为是,异步调用指,用户调用该方法后,无须等待创建结束就可继续做其他操作</param>
  383. public void StartServices(bool ansy)
  384. {
  385. lock (this)
  386. {
  387. createThreadMode = 0;//工作模式0
  388. createThreadProcessRun = true;
  389. createThreadProcessTemp = _minConnection;
  390. if (_ps == PoolState.UnInitialize)
  391. threadCreate.Start();
  392. else if (_ps == PoolState.Stop)
  393. threadCreate.Interrupt();
  394. else
  395. throw new PoolNotStopException();//服务已经运行或者未完全结束
  396. time.Start();
  397. }
  398. if (!ansy)
  399. while (threadCreate.ThreadState != ThreadState.WaitSleepJoin) { Thread.Sleep(50); }//等待可能存在的创建线程结束
  400. }
  401. /// <summary>
  402. /// 停止服务,线程安全
  403. /// </summary>
  404. public void StopServices()
  405. { StopServices(false); }
  406. /// <summary>
  407. /// 停止服务,线程安全
  408. /// <param name="needs">是否必须退出;如果指定为false与StartServices()功能相同,如果指定为true。将未收回的连接资源关闭,这将是危险的。认为可能你的程序正在使用此资源。</param>
  409. /// </summary>
  410. public void StopServices(bool needs)
  411. {
  412. lock (this)
  413. {
  414. if (_ps == PoolState.Run)
  415. {
  416. lock (hs_UseConn)
  417. {
  418. if (needs == true)//必须退出
  419. hs_UseConn.Clear();
  420. else
  421. if (hs_UseConn.Count != 0)
  422. throw new ResCallBackException();//连接池资源未全部回收
  423. }
  424. time.Stop();
  425. while (isThreadCheckRun) { Thread.Sleep(50); }//等待timer事件结束
  426. createThreadProcessRun = false;
  427. while (threadCreate.ThreadState != ThreadState.WaitSleepJoin) { Thread.Sleep(50); }//等待可能存在的创建线程结束
  428. lock (al_All)
  429. {
  430. for (int i = 0; i < al_All.Count; i++)
  431. al_All[i].Dispose();
  432. al_All.Clear();
  433. }
  434. _ps = PoolState.Stop;
  435. }
  436. else
  437. throw new PoolNotRunException();//服务未启动
  438. }
  439. UpdateAttribute();//更新属性
  440. }
  441. public void Dispose()
  442. {
  443. try
  444. {
  445. this.StopServices();
  446. threadCreate.Abort();
  447. }
  448. catch (Exception e) { }
  449. }
  450. #endregion
  451. //--------------------------------------------------------------------
  452. #region 获得连接 与 释放连接
  453. /// <summary>
  454. /// 在连接池中申请一个连接,使用None级别,线程安全
  455. /// </summary>
  456. /// <param name="gui">发起者</param>
  457. /// <returns>返回申请到的连接</returns>
  458. public DbConnection GetConnectionFormPool(object key)
  459. { return GetConnectionFormPool(key, ConnLevel.None); }
  460. /// <summary>
  461. /// 在连接池中申请一个连接,线程安全
  462. /// </summary>
  463. /// <param name="key">申请者</param>
  464. /// <param name="cl">申请的连接级别</param>
  465. /// <returns>返回申请到的连接</returns>
  466. public DbConnection GetConnectionFormPool(object key, ConnLevel cl)
  467. {
  468. lock (this)
  469. {
  470. if (_ps != PoolState.Run)
  471. throw new StateException();//服务状态错误
  472. if (hs_UseConn.Count == MaxConnectionFormPool)
  473. throw new PoolFullException();//连接池已经饱和,不能提供连接
  474. if (hs_UseConn.ContainsKey(key))
  475. throw new KeyExecption();//一个key对象只能申请一个连接
  476. if (cl == ConnLevel.ReadOnly)
  477. return GetConnectionFormPool_ReadOnly(key);//ReadOnly级别
  478. else if (cl == ConnLevel.High)
  479. return GetConnectionFormPool_High(key);//High级别
  480. else if (cl == ConnLevel.None)
  481. return GetConnectionFormPool_None(key);//None级别
  482. else
  483. return GetConnectionFormPool_Bottom(key);//Bottom级别
  484. }
  485. }
  486. /// <summary>
  487. /// 申请一个连接资源,只读方式,线程安全
  488. /// </summary>
  489. /// <param name="key">申请者</param>
  490. /// <returns>申请到的连接对象</returns>
  491. protected DbConnection GetConnectionFormPool_ReadOnly(object key)
  492. {
  493. ConnStruct cs = null;
  494. for (int i = 0; i < al_All.Count; i++)
  495. {
  496. cs = al_All[i];
  497. if (cs.Enable == false || cs.Allot == false || cs.UseDegree == _maxRepeatDegree || cs.IsUse == true)
  498. continue;
  499. return GetConnectionFormPool_Return(key, cs, ConnLevel.ReadOnly); //返回得到的连接
  500. }
  501. return GetConnectionFormPool_Return(key, null, ConnLevel.ReadOnly);
  502. }
  503. /// <summary>
  504. /// 申请一个连接资源,优先级-高,线程安全
  505. /// </summary>
  506. /// <param name="key">申请者</param>
  507. /// <returns>申请到的连接对象</returns>
  508. protected DbConnection GetConnectionFormPool_High(object key)
  509. {
  510. ConnStruct cs = null;
  511. ConnStruct csTemp = null;
  512. for (int i = 0; i < al_All.Count; i++)
  513. {
  514. csTemp = al_All[i];
  515. if (csTemp.Enable == false || csTemp.Allot == false || csTemp.UseDegree == _maxRepeatDegree)//不可以分配跳出本次循环。
  516. {
  517. csTemp = null;
  518. continue;
  519. }
  520. if (csTemp.UseDegree == 0)//得到最合适的
  521. {
  522. cs = csTemp;
  523. break;
  524. }
  525. else//不是最合适的放置到最佳选择中
  526. {
  527. if (cs != null)
  528. {
  529. if (csTemp.UseDegree < cs.UseDegree)
  530. //与上一个最佳选择选出一个最佳的放置到cs中
  531. cs = csTemp;
  532. }
  533. else
  534. cs = csTemp;
  535. }
  536. }
  537. return GetConnectionFormPool_Return(key, cs, ConnLevel.High);//返回最合适的连接
  538. }
  539. /// <summary>
  540. /// 申请一个连接资源,优先级-中,线程安全
  541. /// </summary>
  542. /// <param name="key">申请者</param>
  543. /// <returns>申请到的连接对象</returns>
  544. protected DbConnection GetConnectionFormPool_None(object key)
  545. {
  546. List<ConnStruct> al = new List<ConnStruct>();
  547. ConnStruct cs = null;
  548. for (int i = 0; i < al_All.Count; i++)
  549. {
  550. cs = al_All[i];
  551. if (cs.Enable == false || cs.Allot == false || cs.UseDegree == _maxRepeatDegree)//不可以分配跳出本次循环。
  552. continue;
  553. if (cs.Allot == true)
  554. al.Add(cs);
  555. }
  556. if (al.Count == 0)
  557. return GetConnectionFormPool_Return(key, null, ConnLevel.None);//发出异常
  558. else
  559. return GetConnectionFormPool_Return(key, (al[al.Count / 2]), ConnLevel.None);//返回连接
  560. }
  561. /// <summary>
  562. /// 申请一个连接资源,优先级-低,线程安全
  563. /// </summary>
  564. /// <param name="key">申请者</param>
  565. /// <returns>申请到的连接对象</returns>
  566. protected DbConnection GetConnectionFormPool_Bottom(object key)
  567. {
  568. ConnStruct cs = null;
  569. ConnStruct csTemp = null;
  570. for (int i = 0; i < al_All.Count; i++)
  571. {
  572. csTemp = al_All[i];
  573. if (csTemp.Enable == false || csTemp.Allot == false || csTemp.UseDegree == _maxRepeatDegree)//不可以分配跳出本次循环。
  574. {
  575. csTemp = null;
  576. continue;
  577. }
  578. else//不是最合适的放置到最佳选择中
  579. {
  580. if (cs != null)
  581. {
  582. if (csTemp.UseDegree > cs.UseDegree)
  583. //与上一个最佳选择选出一个最佳的放置到cs中
  584. cs = csTemp;
  585. }
  586. else
  587. cs = csTemp;
  588. }
  589. }
  590. return GetConnectionFormPool_Return(key, cs, ConnLevel.Bottom);//返回最合适的连接
  591. }
  592. /// <summary>
  593. /// 返回DbConnection对象,同时做获得连接时的必要操作
  594. /// </summary>
  595. /// <param name="key">key</param>
  596. /// <param name="cs">ConnStruct对象</param>
  597. /// <param name="cl">级别</param>
  598. /// <param name="readOnly">是否为只读属性</param>
  599. /// <returns></returns>
  600. private DbConnection GetConnectionFormPool_Return(object key, ConnStruct cs, ConnLevel cl)
  601. {
  602. try
  603. {
  604. if (cs == null)
  605. throw new Exception();
  606. cs.Repeat();
  607. hs_UseConn.Add(key, cs);
  608. if (cl == ConnLevel.ReadOnly)
  609. {
  610. cs.Allot = false;
  611. cs.IsRepeat = false;
  612. }
  613. }
  614. catch (Exception e)
  615. {
  616. throw new OccasionExecption();//连接资源耗尽,或错误的访问时机。
  617. }
  618. finally
  619. {
  620. UpdateAttribute();//更新属性
  621. }
  622. return cs.Connection;
  623. }
  624. /// <summary>
  625. /// 释放申请的数据库连接对象,线程安全
  626. /// <param name="key">key表示数据库连接申请者</param>
  627. /// </summary>
  628. public void DisposeConnection(object key)
  629. {
  630. lock (hs_UseConn)
  631. {
  632. ConnStruct cs = null;
  633. if (_ps == PoolState.Run)
  634. {
  635. if (!hs_UseConn.ContainsKey(key))
  636. throw new NotKeyExecption();//无法释放,不存在的key
  637. cs = (ConnStruct)hs_UseConn[key];
  638. cs.IsRepeat = true;
  639. if (cs.Allot == false)
  640. if (cs.Enable == true)
  641. cs.Allot = true;
  642. cs.Remove();
  643. hs_UseConn.Remove(key);
  644. }
  645. else
  646. throw new PoolNotRunException();//服务未启动
  647. }
  648. UpdateAttribute();//更新属性
  649. }
  650. #endregion
  651. //--------------------------------------------------------------------
  652. #region 私有方法
  653. private int createThreadMode = 0;//创建线程工作模式
  654. private int createThreadProcessTemp = 0;//需要创建的连接数
  655. private bool createThreadProcessRun = false;//是否决定创建线程将继续工作,如果不继续工作则线程会将自己处于阻止状态
  656. /// <summary>
  657. /// 创建线程
  658. /// </summary>
  659. private void createThreadProcess()
  660. {
  661. bool join = false;
  662. int createThreadProcessTemp_inside = createThreadProcessTemp;
  663. _ps = PoolState.Initialize;
  664. while (true)
  665. {
  666. join = false;
  667. _ps = PoolState.Run;
  668. if (createThreadProcessRun == false)
  669. {//遇到终止命令
  670. try { threadCreate.Join(); }
  671. catch (Exception e) { }
  672. }
  673. else
  674. {
  675. if (createThreadMode == 0)
  676. {
  677. //------------------------begin mode 创建模式
  678. lock (al_All)
  679. {
  680. if (al_All.Count < createThreadProcessTemp_inside)
  681. al_All.Add(CreateConnection(_connString, _connType));
  682. else
  683. join = true;
  684. }
  685. //------------------------end mode
  686. }
  687. else if (createThreadMode == 1)
  688. {
  689. //------------------------begin mode 增加模式
  690. lock (al_All)
  691. {
  692. if (createThreadProcessTemp_inside != 0)
  693. {
  694. createThreadProcessTemp_inside--;
  695. al_All.Add(CreateConnection(_connString, _connType));
  696. }
  697. else
  698. join = true;
  699. }
  700. //------------------------end mode
  701. }
  702. else
  703. join = true;
  704. //-------------------------------------------------------------------------
  705. if (join == true)
  706. {
  707. UpdateAttribute();//更新属性
  708. try
  709. {
  710. createThreadProcessTemp = 0;
  711. threadCreate.Join();
  712. }
  713. catch (Exception e)
  714. { createThreadProcessTemp_inside = createThreadProcessTemp; }//得到传入的变量
  715. }
  716. }
  717. }
  718. }
  719. /// <summary>
  720. /// 检测事件
  721. /// </summary>
  722. private void time_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
  723. {
  724. ConnStruct cs = null;
  725. time.Stop();//关闭自己
  726. isThreadCheckRun = true;
  727. //如果正在执行创建连接则退出
  728. if (threadCreate.ThreadState != ThreadState.WaitSleepJoin)
  729. return;
  730. //------------------------------------------------------
  731. lock (al_All)
  732. {
  733. int n = 0;
  734. for (int i = 0; i < al_All.Count; i++)
  735. {
  736. cs = al_All[i];
  737. TestConnStruct(cs);//测试
  738. if (cs.Enable == false && cs.RepeatNow == 0)//没有引用的失效连接
  739. {
  740. cs.Close();//关闭它
  741. al_All.Remove(cs);//删除
  742. }
  743. }
  744. }
  745. //------------------------------------------------------
  746. UpdateAttribute();//更新属性
  747. if (_spareRealFormPool < _keepRealConnection)//保留空闲实际连接数不足
  748. createThreadProcessTemp = GetNumOf(_realFormPool, _seepConnection, _maxConnection);
  749. else
  750. createThreadProcessTemp = 0;
  751. //if (createThreadProcessTemp != 0)
  752. // Console.WriteLine("创建" + createThreadProcessTemp);
  753. if (createThreadProcessTemp != 0)
  754. {
  755. //启动创建线程,工作模式1
  756. createThreadMode = 1;
  757. threadCreate.Interrupt();
  758. }
  759. isThreadCheckRun = false;
  760. time.Start();//打开自己
  761. }
  762. /// <summary>
  763. /// 得到当前要增加的量
  764. /// </summary>
  765. private int GetNumOf(int nowNum, int seepNum, int maxNum)
  766. {
  767. if (maxNum >= nowNum + seepNum)
  768. return seepNum;
  769. else
  770. return maxNum - nowNum;
  771. }
  772. /// <summary>
  773. /// 用指定类型创建连接
  774. /// </summary>
  775. /// <param name="conn">连接字符串</param>
  776. /// <param name="cte">连接类型</param>
  777. /// <param name="dt">连接超时时间</param>
  778. /// <returns>返回创建的连接</returns>
  779. private ConnStruct CreateConnection(string conn, ConnTypeEnum cte)
  780. {
  781. DbConnection db = null;
  782. if (cte == ConnTypeEnum.Odbc)
  783. db = new System.Data.Odbc.OdbcConnection(conn);//ODBC数据源连接
  784. else if (cte == ConnTypeEnum.OleDb)
  785. db = new System.Data.OleDb.OleDbConnection(conn);//OLE DB数据连接
  786. else if (cte == ConnTypeEnum.SqlClient)
  787. db = new System.Data.SqlClient.SqlConnection(conn);//SqlServer数据库连接
  788. ConnStruct cs = new ConnStruct(db, cte, DateTime.Now);
  789. cs.Open();
  790. return cs;
  791. }
  792. /// <summary>
  793. /// 测试ConnStruct是否过期
  794. /// </summary>
  795. /// <param name="cs">被测试的ConnStruct</param>
  796. private void TestConnStruct(ConnStruct cs)
  797. {
  798. //此次被分配出去的连接是否在此次之后失效
  799. if (cs.UseDegree == _maxRepeatDegree)
  800. cs.SetConnectionLost();//超过使用次数
  801. if (cs.CreateTime.AddMinutes(_exist).Ticks <= DateTime.Now.Ticks)
  802. cs.SetConnectionLost();//连接超时
  803. if (cs.Connection.State == ConnectionState.Closed)
  804. cs.SetConnectionLost();//连接被关闭
  805. }
  806. /// <summary>
  807. /// 更新属性
  808. /// </summary>
  809. private void UpdateAttribute()
  810. {
  811. int temp_readOnlyFormPool = 0;//连接池已经分配多少只读连接
  812. int temp_potentRealFormPool = 0;//连接池中存在的实际连接数(有效的实际连接)
  813. int temp_spareRealFormPool = 0;//空闲的实际连接
  814. int temp_useRealFormPool = 0;//已分配的实际连接
  815. int temp_spareFormPool = MaxConnectionFormPool;//目前可以提供的连接数
  816. //---------------------------------
  817. lock (hs_UseConn)
  818. {
  819. _useFormPool = hs_UseConn.Count;
  820. }
  821. //---------------------------------
  822. ConnStruct cs = null;
  823. int n = 0;
  824. lock (al_All)
  825. {
  826. _realFormPool = al_All.Count;
  827. for (int i = 0; i < al_All.Count; i++)
  828. {
  829. cs = al_All[i];
  830. //只读
  831. if (cs.Allot == false && cs.IsUse == true && cs.IsRepeat == false)
  832. temp_readOnlyFormPool++;
  833. //有效的实际连接
  834. if (cs.Enable == true)
  835. temp_potentRealFormPool++;
  836. //空闲的实际连接
  837. if (cs.Enable == true && cs.IsUse == false)
  838. temp_spareRealFormPool++;
  839. //已分配的实际连接
  840. if (cs.IsUse == true)
  841. temp_useRealFormPool++;
  842. //目前可以提供的连接数
  843. if (cs.Allot == true)
  844. temp_spareFormPool = temp_spareFormPool - cs.RepeatNow;
  845. else
  846. temp_spareFormPool = temp_spareFormPool - _maxRepeatDegree;
  847. }
  848. }
  849. _readOnlyFormPool = temp_readOnlyFormPool;
  850. _potentRealFormPool = temp_potentRealFormPool;
  851. _spareRealFormPool = temp_spareRealFormPool;
  852. _useRealFormPool = temp_useRealFormPool;
  853. _spareFormPool = temp_spareFormPool;
  854. }
  855. #endregion
  856. }
  857. }