11using System ;
2- using System . Collections . Generic ;
32using System . Collections . Concurrent ;
4- using System . Linq ;
3+ using System . Collections . Generic ;
54using System . Text ;
6- using System . Text . RegularExpressions ;
75using System . Threading ;
86using System . Threading . Tasks ;
97
@@ -63,33 +61,30 @@ public partial class ObjectPool<T> : IObjectPool<T>
6361 public bool IsAvailable => this . UnavailableException == null ;
6462 public Exception UnavailableException { get ; private set ; }
6563 public DateTime ? UnavailableTime { get ; private set ; }
64+ public DateTime ? AvailableTime { get ; private set ; }
6665 private object UnavailableLock = new object ( ) ;
6766 private bool running = true ;
6867
69- public bool SetUnavailable ( Exception exception )
68+ public bool SetUnavailable ( Exception exception , DateTime lastGetTime )
7069 {
71-
7270 bool isseted = false ;
73-
7471 if ( exception != null && UnavailableException == null )
7572 {
76-
7773 lock ( UnavailableLock )
7874 {
79-
8075 if ( UnavailableException == null )
8176 {
82-
77+ if ( lastGetTime < AvailableTime ) return false ; //已经恢复
8378 UnavailableException = exception ;
8479 UnavailableTime = DateTime . Now ;
80+ AvailableTime = null ;
8581 isseted = true ;
8682 }
8783 }
8884 }
8985
9086 if ( isseted )
9187 {
92-
9388 Policy . OnUnavailable ( ) ;
9489 CheckAvailable ( Policy . CheckAvailableInterval ) ;
9590 }
@@ -103,41 +98,31 @@ public bool SetUnavailable(Exception exception)
10398 /// <param name="interval"></param>
10499 private void CheckAvailable ( int interval )
105100 {
106-
107101 new Thread ( ( ) =>
108102 {
109-
110103 if ( UnavailableException != null )
111104 TestTrace . WriteLine ( $ "【{ Policy . Name } 】Next recovery time:{ DateTime . Now . AddSeconds ( interval ) } ", ConsoleColor . DarkYellow ) ;
112105
113106 while ( UnavailableException != null )
114107 {
115-
116108 if ( running == false ) return ;
117-
118109 Thread . CurrentThread . Join ( TimeSpan . FromSeconds ( interval ) ) ;
119-
120110 if ( running == false ) return ;
121111
122112 try
123113 {
124-
125114 var conn = GetFree ( false ) ;
126115 if ( conn == null ) throw new Exception ( CoreStrings . Available_Failed_Get_Resource ( "CheckAvailable" , this . Statistics ) ) ;
127116
128117 try
129118 {
130-
131119 if ( Policy . OnCheckAvailable ( conn ) == false ) throw new Exception ( CoreStrings . Available_Thrown_Exception ( "CheckAvailable" ) ) ;
132120 break ;
133-
134121 }
135122 finally
136123 {
137-
138124 Return ( conn ) ;
139125 }
140-
141126 }
142127 catch ( Exception ex )
143128 {
@@ -156,61 +141,50 @@ private void RestoreToAvailable()
156141 bool isRestored = false ;
157142 if ( UnavailableException != null )
158143 {
159-
160144 lock ( UnavailableLock )
161145 {
162-
163146 if ( UnavailableException != null )
164147 {
165-
166148 UnavailableException = null ;
167149 UnavailableTime = null ;
150+ AvailableTime = DateTime . Now ;
168151 isRestored = true ;
169152 }
170153 }
171154 }
172155
173156 if ( isRestored )
174157 {
175-
176158 lock ( _allObjectsLock )
177159 _allObjects . ForEach ( a => a . LastGetTime = a . LastReturnTime = new DateTime ( 2000 , 1 , 1 ) ) ;
178160
179161 Policy . OnAvailable ( ) ;
180-
181162 TestTrace . WriteLine ( $ "【{ Policy . Name } 】Recovered", ConsoleColor . DarkGreen ) ;
182163 }
183164 }
184165
185166 protected bool LiveCheckAvailable ( )
186167 {
187-
188168 try
189169 {
190-
191170 var conn = GetFree ( false ) ;
192171 if ( conn == null ) throw new Exception ( CoreStrings . Available_Failed_Get_Resource ( "LiveCheckAvailable" , this . Statistics ) ) ;
193172
194173 try
195174 {
196-
197175 if ( Policy . OnCheckAvailable ( conn ) == false ) throw new Exception ( CoreStrings . Available_Thrown_Exception ( "LiveCheckAvailable" ) ) ;
198-
199176 }
200177 finally
201178 {
202-
203179 Return ( conn ) ;
204180 }
205-
206181 }
207182 catch
208183 {
209184 return false ;
210185 }
211186
212187 RestoreToAvailable ( ) ;
213-
214188 return true ;
215189 }
216190
@@ -282,7 +256,6 @@ private Object<T> GetFree(bool checkAvailable)
282256
283257 if ( ( _freeObjects . TryPop ( out var obj ) == false || obj == null ) && _allObjects . Count < Policy . PoolSize )
284258 {
285-
286259 lock ( _allObjectsLock )
287260 if ( _allObjects . Count < Policy . PoolSize )
288261 _allObjects . Add ( obj = new Object < T > { Pool = this , Id = _allObjects . Count + 1 } ) ;
@@ -310,12 +283,9 @@ private Object<T> GetFree(bool checkAvailable)
310283
311284 public Object < T > Get ( TimeSpan ? timeout = null )
312285 {
313-
314286 var obj = GetFree ( true ) ;
315-
316287 if ( obj == null )
317288 {
318-
319289 var queueItem = new GetSyncQueueInfo ( ) ;
320290
321291 _getSyncQueue . Enqueue ( queueItem ) ;
@@ -336,9 +306,7 @@ public Object<T> Get(TimeSpan? timeout = null)
336306
337307 if ( obj == null )
338308 {
339-
340309 Policy . OnGetTimeout ( ) ;
341-
342310 if ( Policy . IsThrowGetTimeoutException )
343311 throw new TimeoutException ( CoreStrings . ObjectPool_Get_Timeout ( Policy . Name , "Get" , timeout . Value . TotalSeconds ) ) ;
344312
@@ -358,6 +326,7 @@ public Object<T> Get(TimeSpan? timeout = null)
358326
359327 obj . LastGetThreadId = Thread . CurrentThread . ManagedThreadId ;
360328 obj . LastGetTime = DateTime . Now ;
329+ obj . LastGetTimeCopy = DateTime . Now ;
361330 Interlocked . Increment ( ref obj . _getTimes ) ;
362331
363332 return obj ;
@@ -367,12 +336,9 @@ public Object<T> Get(TimeSpan? timeout = null)
367336#else
368337 async public Task < Object < T > > GetAsync ( )
369338 {
370-
371339 var obj = GetFree ( true ) ;
372-
373340 if ( obj == null )
374341 {
375-
376342 if ( Policy . AsyncGetCapacity > 0 && _getAsyncQueue . Count >= Policy . AsyncGetCapacity - 1 )
377343 throw new OutOfMemoryException ( CoreStrings . ObjectPool_GetAsync_Queue_Long ( Policy . Name , Policy . AsyncGetCapacity ) ) ;
378344
@@ -412,6 +378,7 @@ async public Task<Object<T>> GetAsync()
412378
413379 obj . LastGetThreadId = Thread . CurrentThread . ManagedThreadId ;
414380 obj . LastGetTime = DateTime . Now ;
381+ obj . LastGetTimeCopy = DateTime . Now ;
415382 Interlocked . Increment ( ref obj . _getTimes ) ;
416383
417384 return obj ;
@@ -420,40 +387,31 @@ async public Task<Object<T>> GetAsync()
420387
421388 public void Return ( Object < T > obj , bool isReset = false )
422389 {
423-
424390 if ( obj == null ) return ;
425-
426391 if ( obj . _isReturned ) return ;
427392
428393 if ( running == false )
429394 {
430-
431395 Policy . OnDestroy ( obj . Value ) ;
432396 try { ( obj . Value as IDisposable ) ? . Dispose ( ) ; } catch { }
433-
434397 return ;
435398 }
436399
437400 if ( isReset ) obj . ResetValue ( ) ;
438-
439401 bool isReturn = false ;
440402
441403 while ( isReturn == false && _getQueue . TryDequeue ( out var isAsync ) )
442404 {
443-
444405 if ( isAsync == false )
445406 {
446-
447407 if ( _getSyncQueue . TryDequeue ( out var queueItem ) && queueItem != null )
448408 {
449-
450409 lock ( queueItem . Lock )
451410 if ( queueItem . IsTimeout == false )
452411 queueItem . ReturnValue = obj ;
453412
454413 if ( queueItem . ReturnValue != null )
455414 {
456-
457415 obj . LastReturnThreadId = Thread . CurrentThread . ManagedThreadId ;
458416 obj . LastReturnTime = DateTime . Now ;
459417
@@ -469,14 +427,11 @@ public void Return(Object<T> obj, bool isReset = false)
469427
470428 try { queueItem . Dispose ( ) ; } catch { }
471429 }
472-
473430 }
474431 else
475432 {
476-
477433 if ( _getAsyncQueue . TryDequeue ( out var tcs ) && tcs != null && tcs . Task . IsCanceled == false )
478434 {
479-
480435 obj . LastReturnThreadId = Thread . CurrentThread . ManagedThreadId ;
481436 obj . LastReturnTime = DateTime . Now ;
482437
@@ -509,11 +464,9 @@ public void Return(Object<T> obj, bool isReset = false)
509464
510465 public void Dispose ( )
511466 {
512-
513467 running = false ;
514468
515469 while ( _freeObjects . TryPop ( out var fo ) ) ;
516-
517470 while ( _getSyncQueue . TryDequeue ( out var sync ) )
518471 {
519472 try { sync . Wait . Set ( ) ; } catch { }
@@ -535,13 +488,9 @@ public void Dispose()
535488
536489 class GetSyncQueueInfo : IDisposable
537490 {
538-
539491 internal ManualResetEventSlim Wait { get ; set ; } = new ManualResetEventSlim ( ) ;
540-
541492 internal Object < T > ReturnValue { get ; set ; }
542-
543493 internal object Lock = new object ( ) ;
544-
545494 internal bool IsTimeout { get ; set ; } = false ;
546495
547496 public void Dispose ( )
0 commit comments