private void ItemCompleted(CustomThreadPool pool, ThreadPoolWorkItem workitem)
        {
            var item = workitem as DownloadItem;
            if (item == null)
                return;

            InvokeFileDownloaded(item.Uri);
        }
        /// <summary>
        /// Raises the AfterWorkItem event
        /// </summary>
        void OnAfterWorkItem(ThreadPoolWorkItem workItem)
        {
            AfterWorkItemHandler delegateToFire;

            lock (eventLock)
            {
                delegateToFire = afterWorkItem;
            }
            if (delegateToFire != null)
            {
                delegateToFire(this, workItem);
            }
        }
        /// <summary>
        /// Adds a work item to the queue and potentially start a new thread.
        /// A thread is started if there are no idle threads or if there is already
        /// something on the queue - but in each case, only if the total number of
        /// threads is less than the maximum.
        /// </summary>
        /// <param name="workItem">The actual work item to add to the queue.</param>
        public void AddWorkItem(ThreadPoolWorkItem workItem)
        {
            if (workItem == null)
            {
                throw new ArgumentNullException("workItem");
            }
            bool startNewThread;

            lock (stateLock)
            {
                lock (queueLock)
                {
                    if (queue.Count == 0)
                    {
                        queue.Enqueue(workItem);
                    }
                    else
                    {
                        // Work out where in the queue the item should go

                        // Common case: it belongs at the end
                        if (((ThreadPoolWorkItem)queue[queue.Count - 1]).Priority >= workItem.Priority)
                        {
                            queue.Enqueue(workItem);
                        }
                        else
                        {
                            // This will find the complement of the correct position, due to the
                            // "interesting" nature of PriorityComparer.
                            int position = queue.BinarySearch(workItem, PriorityComparer.Instance);
                            queue.Enqueue(workItem, ~position);
                        }
                    }
                    startNewThread = (WorkingThreads + queue.Count > TotalThreads) &&
                                     (TotalThreads < MaxThreads);
                    // Always pulse the queueLock, whether there's something waiting or not.
                    // This is easier than trying to work out for sure whether or not it's
                    // worth pulsing, and errs on the side of caution.
                    Monitor.Pulse(queueLock);
                }
            }
            if (startNewThread)
            {
                StartWorkerThread();
            }
        }
        /// <summary>
        /// Executes the given work item, firing the BeforeWorkItem and AfterWorkItem events,
        /// and incrementing and decrementing the number of working threads.
        /// </summary>
        /// <param name="job">The work item to execute</param>
        void ExecuteWorkItem(ThreadPoolWorkItem job)
        {
            lock (stateLock)
            {
                workingThreads++;
#if NET461
                Thread.CurrentThread.Priority = workerThreadPriority;
#endif
                Thread.CurrentThread.IsBackground = workerThreadsAreBackground;
            }
            try
            {
                bool cancel;
                OnBeforeWorkItem(job, out cancel);
                if (cancel)
                {
                    return;
                }
                try
                {
                    job.Invoke();
                }
                catch (Exception e)
                {
                    OnException(job, e);
                    return;
                }
                OnAfterWorkItem(job);
            }
            finally
            {
                lock (stateLock)
                {
#if NET461
                    Thread.CurrentThread.Priority = workerThreadPriority;
#endif
                    Thread.CurrentThread.IsBackground = workerThreadsAreBackground;
                    workingThreads--;
                }
            }
        }
 /// <summary>
 /// Cancels the first work item with the specified ID, if there is one.
 /// Note that items which have been taken off the queue and are running
 /// or about to be started cannot be cancelled.
 /// </summary>
 /// <param name="id">The ID of the work item to cancel</param>
 public bool CancelWorkItem(object id)
 {
     if (id == null)
     {
         throw new ArgumentNullException("id");
     }
     lock (queueLock)
     {
         for (int i = 0; i < queue.Count; i++)
         {
             ThreadPoolWorkItem item    = (ThreadPoolWorkItem)queue[i];
             object             otherID = item.ID;
             if (otherID != null && id.Equals(otherID))
             {
                 queue.RemoveAt(i);
                 return(true);
             }
         }
     }
     return(false);
 }
        /// <summary>
        /// Main worker thread loop. This picks jobs off the queue and executes
        /// them, until it's time to die.
        /// </summary>
        void WorkerThreadLoop()
        {
            // Big try/finally block just to decrement the number of threads whatever happens.
            try
            {
                DateTime lastJob = DateTime.UtcNow;
                while (true)
                {
                    lock (stateLock)
                    {
                        if (TotalThreads > MaxThreads)
                        {
                            return;
                        }
                    }
                    int waitPeriod = CalculateWaitPeriod(lastJob);

                    ThreadPoolWorkItem job = GetNextWorkItem(waitPeriod);

                    // No job? Check whether or not we should die
                    if (job == null)
                    {
                        if (CheckIfThreadShouldQuit(lastJob))
                        {
                            return;
                        }
                    }
                    else
                    {
                        ExecuteWorkItem(job);
                        lastJob = DateTime.UtcNow;
                    }
                }
            }
            finally
            {
                OnWorkerThreadExit();
            }
        }
        /// <summary>
        /// Raises the BeforeWorkItem event
        /// </summary>
        /// <param name="workItem">The work item which is about to execute</param>
        /// <param name="cancel">Whether or not the work item was cancelled by an event handler</param>
        void OnBeforeWorkItem(ThreadPoolWorkItem workItem, out bool cancel)
        {
            cancel = false;
            BeforeWorkItemHandler delegateToFire;

            lock (eventLock)
            {
                delegateToFire = beforeWorkItem;
            }
            if (delegateToFire != null)
            {
                Delegate[] delegates = delegateToFire.GetInvocationList();
                foreach (BeforeWorkItemHandler d in delegates)
                {
                    d(this, workItem, ref cancel);
                    if (cancel)
                    {
                        return;
                    }
                }
            }
        }
        /// <summary>
        /// Raises the WorkerException event.
        /// TODO: Write to the event log if no exception handlers are attached?
        /// </summary>
        void OnException(ThreadPoolWorkItem workItem, Exception e)
        {
            ThreadPoolExceptionHandler eh;

            lock (eventLock)
            {
                eh = exceptionHandler;
            }
            if (eh != null)
            {
                Delegate[] delegates = eh.GetInvocationList();
                bool       handled   = false;
                foreach (ThreadPoolExceptionHandler d in delegates)
                {
                    d(this, workItem, e, ref handled);
                    if (handled)
                    {
                        return;
                    }
                }
            }
        }
Example #9
0
            void pool_WorkerException(CustomThreadPool pool, ThreadPoolWorkItem workItem, Exception e, ref bool handled)
            {
                var mine = workItem.Parameters[0] as IndexWorkItem;

                if (mine != null)
                {
                    mine.FireError(e, ref handled);
                }
            }
Example #10
0
            void pool_BeforeWorkItem(CustomThreadPool pool, ThreadPoolWorkItem workItem, ref bool cancel)
            {
                var mine = workItem.Parameters[0] as IndexWorkItem;

                if (mine != null)
                {
                    mine.FireBeforeRun();
                }
            }
Example #11
0
            void pool_AfterWorkItem(CustomThreadPool pool, ThreadPoolWorkItem workItem)
            {
                var mine = workItem.Parameters[0] as IndexWorkItem;

                if (mine != null)
                {
                    mine.FireComplete();
                }
            }
Example #12
0
 void Fire(IndexWorkItem workItem)
 {
     var wi = new ThreadPoolWorkItem("", true, false, 1, new ThreadStart(DoIndexing), workItem);
     pool.AddWorkItem(wi);
 }