public ThreadedRequest <In, Out> Post(ThreadedRequest <In, Out> request)
        {
            if (request == null)
            {
                Debug.Warn("Null request passed into Post method on threaded.");
                return(null);
            }
            if (request.IsInPool)
            {
                Debug.Warn("Attempt to post a request that is currently in the pool: be careful with request lifespans! A request cannot be re-used!");
                return(null);
            }
            if (request.IsCancelled)
            {
                request.UponProcessed?.Invoke(ThreadedRequestResult.Cancelled, default(Out));
                request.ReturnToPool();
                return(null);
            }

            lock (KEY)
            {
                pending.Enqueue(request);
            }
            return(request);
        }
        protected virtual void RunThread(object arg)
        {
            int threadIndex = (int)arg;
            IThreadProcessor <In, Out> processor = processors[threadIndex];
            Stopwatch watch = new Stopwatch();

            const int IDLE_TIME = 5;

            while (IsRunning)
            {
                if (pending.Count > 0)
                {
                    ThreadedRequest <In, Out> todo = null;
                    lock (KEY)
                    {
                        if (pending.Count > 0)
                        {
                            todo = pending.Dequeue();
                        }
                    }

                    if (todo != null && !todo.IsCancelled)
                    {
                        Statistics[threadIndex].CumulativeProcessed++;
                        _processedIncrement++;
                        watch.Start();
                        Out output = default(Out);
                        try
                        {
                            output = processor.Process(todo.InputArgs);
                        }
                        catch (Exception)
                        {
                            PostResult(() =>
                            {
                                todo.UponProcessed?.Invoke(ThreadedRequestResult.Error, output);
                                todo.ReturnToPool();
                            });
                            continue;
                        }
                        PostResult(() =>
                        {
                            todo.UponProcessed?.Invoke(ThreadedRequestResult.Run, output);
                            todo.ReturnToPool();
                        });
                        watch.Stop();
                        Statistics[threadIndex].CumulativeUsage += (float)watch.Elapsed.TotalSeconds;
                        if (Statistics[threadIndex].CumulativeUsage > 1f)
                        {
                            Statistics[threadIndex].CumulativeUsage = 1f;
                        }
                        Statistics[threadIndex].AddProcessTime((float)watch.Elapsed.TotalSeconds);
                        watch.Reset();
                    }
                    else if (todo != null && todo.IsCancelled)
                    {
                        PostResult(() =>
                        {
                            todo.UponProcessed?.Invoke(ThreadedRequestResult.Cancelled, default(Out));
                            todo.ReturnToPool();
                        });
                    }
                }
                else
                {
                    Thread.Sleep(IDLE_TIME);
                }
            }
        }