moel@345: // Stephen Toub moel@345: // stoub@microsoft.com moel@345: moel@345: using System; moel@345: using System.Collections.Generic; moel@345: using System.Text; moel@345: using System.Threading; moel@345: moel@345: namespace Aga.Controls.Threading moel@345: { moel@345: public class AbortableThreadPool moel@345: { moel@345: private LinkedList _callbacks = new LinkedList(); moel@345: private Dictionary _threads = new Dictionary(); moel@345: moel@345: public WorkItem QueueUserWorkItem(WaitCallback callback) moel@345: { moel@345: return QueueUserWorkItem(callback, null); moel@345: } moel@345: moel@345: public WorkItem QueueUserWorkItem(WaitCallback callback, object state) moel@345: { moel@345: if (callback == null) throw new ArgumentNullException("callback"); moel@345: moel@345: WorkItem item = new WorkItem(callback, state, ExecutionContext.Capture()); moel@345: lock (_callbacks) moel@345: { moel@345: _callbacks.AddLast(item); moel@345: } moel@345: ThreadPool.QueueUserWorkItem(new WaitCallback(HandleItem)); moel@345: return item; moel@345: } moel@345: moel@345: private void HandleItem(object ignored) moel@345: { moel@345: WorkItem item = null; moel@345: try moel@345: { moel@345: lock (_callbacks) moel@345: { moel@345: if (_callbacks.Count > 0) moel@345: { moel@345: item = _callbacks.First.Value; moel@345: _callbacks.RemoveFirst(); moel@345: } moel@345: if (item == null) moel@345: return; moel@345: _threads.Add(item, Thread.CurrentThread); moel@345: moel@345: } moel@345: ExecutionContext.Run(item.Context, moel@345: delegate { item.Callback(item.State); }, null); moel@345: } moel@345: finally moel@345: { moel@345: lock (_callbacks) moel@345: { moel@345: if (item != null) moel@345: _threads.Remove(item); moel@345: } moel@345: } moel@345: } moel@345: moel@345: public bool IsMyThread(Thread thread) moel@345: { moel@345: lock (_callbacks) moel@345: { moel@345: foreach (Thread t in _threads.Values) moel@345: { moel@345: if (t == thread) moel@345: return true; moel@345: } moel@345: return false; moel@345: } moel@345: } moel@345: moel@345: public WorkItemStatus Cancel(WorkItem item, bool allowAbort) moel@345: { moel@345: if (item == null) moel@345: throw new ArgumentNullException("item"); moel@345: lock (_callbacks) moel@345: { moel@345: LinkedListNode node = _callbacks.Find(item); moel@345: if (node != null) moel@345: { moel@345: _callbacks.Remove(node); moel@345: return WorkItemStatus.Queued; moel@345: } moel@345: else if (_threads.ContainsKey(item)) moel@345: { moel@345: if (allowAbort) moel@345: { moel@345: _threads[item].Abort(); moel@345: _threads.Remove(item); moel@345: return WorkItemStatus.Aborted; moel@345: } moel@345: else moel@345: return WorkItemStatus.Executing; moel@345: } moel@345: else moel@345: return WorkItemStatus.Completed; moel@345: } moel@345: } moel@345: moel@345: public void CancelAll(bool allowAbort) moel@345: { moel@345: lock (_callbacks) moel@345: { moel@345: _callbacks.Clear(); moel@345: if (allowAbort) moel@345: { moel@345: foreach (Thread t in _threads.Values) moel@345: t.Abort(); moel@345: } moel@345: } moel@345: } moel@345: } moel@345: }