123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- using PaintDotNet.SystemLayer;
- using System;
- using System.Collections;
- using System.Threading;
- namespace PaintDotNet.Threading
- {
- /// <summary>
- /// Uses the .NET ThreadPool to do our own type of thread pool. The main difference
- /// here is that we limit our usage of the thread pool, and that we can also drain
- /// the threads we have ("fence"). The default maximum number of threads is
- /// Processor.LogicalCpuCount.
- /// </summary>
- public class ThreadPool
- {
- private static ThreadPool global = new ThreadPool(2 * Processor.LogicalCpuCount);
- public static ThreadPool Global
- {
- get
- {
- return global;
- }
- }
- private ArrayList exceptions = ArrayList.Synchronized(new ArrayList());
- private bool useFXTheadPool;
- public static int MinimumCount
- {
- get
- {
- return WaitableCounter.MinimumCount;
- }
- }
- public static int MaximumCount
- {
- get
- {
- return WaitableCounter.MaximumCount;
- }
- }
- public Exception[] Exceptions
- {
- get
- {
- return (Exception[])this.exceptions.ToArray(typeof(Exception));
- }
- }
- public void ClearExceptions()
- {
- exceptions.Clear();
- }
- public void DrainExceptions()
- {
- if (this.exceptions.Count > 0)
- {
- throw new WorkerThreadException("Worker thread threw an exception", (Exception)this.exceptions[0]);
- }
- ClearExceptions();
- }
- private WaitableCounter counter;
- public ThreadPool()
- : this(Processor.LogicalCpuCount)
- {
- }
- public ThreadPool(int maxThreads)
- : this(maxThreads, true)
- {
- }
- public ThreadPool(int maxThreads, bool useFXThreadPool)
- {
- if (maxThreads < MinimumCount || maxThreads > MaximumCount)
- {
- throw new ArgumentOutOfRangeException("maxThreads", "must be between " + MinimumCount.ToString() + " and " + MaximumCount.ToString() + " inclusive");
- }
- this.counter = new WaitableCounter(maxThreads);
- this.useFXTheadPool = useFXThreadPool;
- }
- /*
- private sealed class FunctionCallTrampoline
- {
- private Delegate theDelegate;
- private object[] parameters;
- public void WaitCallback(object ignored)
- {
- theDelegate.DynamicInvoke(this.parameters);
- }
- public FunctionCallTrampoline(Delegate theDelegate, object[] parameters)
- {
- this.theDelegate = theDelegate;
- this.parameters = parameters;
- }
- }
- public void QueueFunctionCall(Delegate theDelegate, params object[] parameters)
- {
- FunctionCallTrampoline fct = new FunctionCallTrampoline(theDelegate, parameters);
- QueueUserWorkItem(fct.WaitCallback, null);
- }
- */
- public void QueueUserWorkItem(WaitCallback callback)
- {
- QueueUserWorkItem(callback, null);
- }
- public void QueueUserWorkItem(WaitCallback callback, object state)
- {
- IDisposable token = counter.AcquireToken();
- ThreadWrapperContext twc = new ThreadWrapperContext(callback, state, token, this.exceptions);
- if (this.useFXTheadPool)
- {
- System.Threading.ThreadPool.QueueUserWorkItem(new WaitCallback(twc.ThreadWrapper), twc);
- }
- else
- {
- Thread thread = new Thread(new ThreadStart(twc.ThreadWrapper));
- thread.IsBackground = true;
- thread.Start();
- }
- }
- public bool IsDrained(uint msTimeout)
- {
- bool result = counter.IsEmpty(msTimeout);
- if (result)
- {
- Drain();
- }
- return result;
- }
- public bool IsDrained()
- {
- return IsDrained(0);
- }
- public void Drain()
- {
- counter.WaitForEmpty();
- DrainExceptions();
- }
- private sealed class ThreadWrapperContext
- {
- private WaitCallback callback;
- private object context;
- private IDisposable counterToken;
- private ArrayList exceptionsBucket;
- public ThreadWrapperContext(WaitCallback callback, object context,
- IDisposable counterToken, ArrayList exceptionsBucket)
- {
- this.callback = callback;
- this.context = context;
- this.counterToken = counterToken;
- this.exceptionsBucket = exceptionsBucket;
- }
- public void ThreadWrapper()
- {
- using (IDisposable token = this.counterToken)
- {
- try
- {
- this.callback(this.context);
- }
- catch (Exception ex)
- {
- this.exceptionsBucket.Add(ex);
- }
- }
- }
- public void ThreadWrapper(object state)
- {
- ThreadWrapper();
- }
- }
- }
- }
|