// Worker threads come here to take items off the work queue.
 // Multiple threads loop around here taking items off the work queue and
 //   processing them. When there are no more things to do, the threads
 //   return which puts them back in the thread pool.
 private void DoWork(object x)
 {
     while (m_workItems.Count > 0)
     {
         DoLaterBase w = null;
         lock (m_workItems) {
             if (m_workItems.Count > 0)
             {
                 w = m_workItems.Dequeue();
             }
         }
         if (w != null)
         {
             try {
                 if (!w.DoIt())
                 {
                     // LogManager.Log.Log(LogLevel.DRENDERDETAIL, "{0}.DoLater: DoWork: DoEvenLater", m_queueName);
                     DoItEvenLater(w);
                 }
             }
             catch (Exception e) {
                 LogManager.Log.Log(LogLevel.DBADERROR, "{0}.DoLater: DoWork: EXCEPTION: {1}",
                                    m_queueName, e);
                 // we drop the work item in  the belief that it will exception again next time
             }
         }
     }
     lock (m_workItems) {
         m_activeWorkProcessors--; // not sure if this is atomic
     }
 }
        // A thread from the outside world calls in here to do some work on the queue
        // We process work items on the queue until the queue is empty or we reach 'maximumCost'.
        // Each queued item has a delay (a time in the future when it can be done) and a
        // cost. As the work items are done, the cost is added up.
        // This means the thread coming in can count on being here only a limited amount
        // of time.
        public void ProcessQueue(int maximumCost)
        {
            int         totalCost    = 0;
            int         totalCounter = 100;
            int         now          = System.Environment.TickCount;
            DoLaterBase found        = null;

            while ((totalCost < maximumCost) && (totalCounter > 0) && (m_workQueue.Count > 0))
            {
                now   = System.Environment.TickCount;
                found = null;
                lock (m_workQueue) {
                    // find an entry in the list who's time has come
                    foreach (DoLaterBase ww in m_workQueue)
                    {
                        if (ww.remainingWait < now)
                        {
                            found = ww;
                            break;
                        }
                    }
                    if (found != null)
                    {
                        // if found, remove from list
                        m_workQueue.Remove(found);
                    }
                }
                if (found == null)
                {
                    // if nothing found, we're done
                    break;
                }
                else
                {
                    // try to do the operation
                    totalCounter--;
                    if (found.DoIt())
                    {
                        // if it worked, count it as successful
                        totalCost += found.cost;
                    }
                    else
                    {
                        // if it didn't work, requeue it for later
                        ((OnDemandWorkQueue)found.containingClass).DoLaterRequeue(ref found);
                    }
                }
            }
        }