public void DoWork()
        {
            try {
                while (mKeepAlive)
                {
                    mSignal.WaitOne();

                    mActiveWorkItem.DoWork();

                    var finishedWorkItem = mActiveWorkItem;
                    mActiveWorkItem = null;

                    // Signal the thread pool that this work is complete. We will then
                    // call the work item's callback method to signal the original caller.
                    mOnFinishedCallback(this, finishedWorkItem);

                    // Wait for next work
                    mSignal.Reset();
                    mIsWorking = false;
                }
            }
            catch (ThreadAbortException t) {
                Debug.LogWarning("A worker thread has been aborted in the thread pool: " + t.Message);
            }
            finally {
                mActiveWorkItem = null;
                mSignal.Close();
            }
        }
        // Called from single-threaded context
        public void AssignWork(ThreadedWork workToDo)
        {
            Precondition.IsNotNull(workToDo);

            if (!mIsWorking)
            {
                mIsWorking      = true;
                mActiveWorkItem = workToDo;

                // Start work processing
                mSignal.Set();
            }
        }
        /// <summary>
        /// Enqueues work to be done. Note that this must be called from the main thread,
        /// it is not thread-safe. The pool only supports a maximum number of work that can
        /// be done concurrently as well as work that is pending. If both pipelines are at
        /// capacity then the function will return false and the work won't be enqueued.
        /// </summary>
        /// <returns>True if the work was enqueued.</returns>
        public bool EnqueueWork(ThreadedWork workRequest)
        {
            if (mPendingTasks.Count < mMaxQueueSize)
            {
                mPendingTasks.Enqueue(workRequest);

                // Signal that there's work afoot. This may or may not dequeue the
                // next item however. In either case, we return true since we could
                // only have hoped to enqueue it.
                TryToPickupNextWork();
                return(true);
            }

            return(false);
        }
        private void WorkerFinishedHandler(Worker worker, ThreadedWork finishedWorkItem)
        {
            // TODO: This might be a bug.
            // Investigate if we need to marshal this back onto the main thread if it's not already
            // on the main thread. Otherwise we break the restriction that we cannot enqueue new work from
            // off-thread

            // Signal the original caller that the requested work is complete. We guarantee
            // that the just-finished worker instance is immediately ready for the next task
            // once you've reached this callback.
            if (mEnableWorkerCallbacks)
            {
                finishedWorkItem.FinishedWorkCallback();
            }

            // Now that a worker has been freed up, we can tell the thread pool to try
            // and pick up the next task.
            if (mEnableDoWorkImmediatelyOnCompletion)
            {
                TryToPickupNextWork();
            }
        }