From c983870fb72e51452925ba42d97d127f7bdeac73 Mon Sep 17 00:00:00 2001 From: sjdirect Date: Wed, 1 Apr 2015 08:30:28 -0700 Subject: [PATCH] Fixes #68, "When you cancel the crawl job, the WebCrawler will dispose the _threadManager and its _resetEvent will also be displsed. But the ThreadManager class can't make sure that all threads running have been completed at the time. So if a thread is running the RunAction method and it will catch a OperationCanceledException exception and finally _resetEvent.Set() will throw a exception said the safe handle was closed." --- Abot/Util/ThreadManager.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Abot/Util/ThreadManager.cs b/Abot/Util/ThreadManager.cs index 0de47dec..7bf8f47a 100644 --- a/Abot/Util/ThreadManager.cs +++ b/Abot/Util/ThreadManager.cs @@ -39,6 +39,7 @@ public abstract class ThreadManager : IThreadManager protected int _numberOfRunningThreads = 0; protected ManualResetEvent _resetEvent = new ManualResetEvent(true); protected Object _locker = new Object(); + protected bool _isDisplosed = false; public ThreadManager(int maxThreads) { @@ -68,13 +69,13 @@ public virtual void DoWork(Action action) if (_abortAllCalled) throw new InvalidOperationException("Cannot call DoWork() after AbortAll() or Dispose() have been called."); - if (MaxThreads > 1) + if (!_isDisplosed && MaxThreads > 1) { _resetEvent.WaitOne(); lock (_locker) { _numberOfRunningThreads++; - if (_numberOfRunningThreads >= MaxThreads) + if (!_isDisplosed && _numberOfRunningThreads >= MaxThreads) _resetEvent.Reset(); _logger.DebugFormat("Starting another thread, increasing running threads to [{0}].", _numberOfRunningThreads); @@ -97,6 +98,7 @@ public virtual void Dispose() { AbortAll(); _resetEvent.Dispose(); + _isDisplosed = true; } public virtual bool HasRunningThreads() @@ -129,7 +131,7 @@ protected virtual void RunAction(Action action, bool decrementRunningThreadCount { _numberOfRunningThreads--; _logger.DebugFormat("[{0}] threads are running.", _numberOfRunningThreads); - if (_numberOfRunningThreads < MaxThreads) + if (!_isDisplosed && _numberOfRunningThreads < MaxThreads) _resetEvent.Set(); } }