External/Aga.Controls/Threading/AbortableThreadPool.cs
author moel.mich
Wed, 18 Jul 2012 19:45:59 +0000
changeset 366 667c75cad937
permissions -rw-r--r--
Changed the system tray icon font scaling to adapt to the size of the tray icon in pixels, because on Windows 7 the tray icon scales with the system font size, while on Windows XP the tray icons are always 16 pixels large.
     1 // Stephen Toub
     2 // stoub@microsoft.com
     3 
     4 using System;
     5 using System.Collections.Generic;
     6 using System.Text;
     7 using System.Threading;
     8 
     9 namespace Aga.Controls.Threading
    10 {
    11 	public class AbortableThreadPool
    12 	{
    13 		private LinkedList<WorkItem> _callbacks = new LinkedList<WorkItem>();
    14 		private Dictionary<WorkItem, Thread> _threads = new Dictionary<WorkItem, Thread>();
    15 
    16 		public WorkItem QueueUserWorkItem(WaitCallback callback)
    17 		{
    18 			return QueueUserWorkItem(callback, null);
    19 		}
    20 
    21 		public WorkItem QueueUserWorkItem(WaitCallback callback, object state)
    22 		{
    23 			if (callback == null) throw new ArgumentNullException("callback");
    24 
    25 			WorkItem item = new WorkItem(callback, state, ExecutionContext.Capture());
    26 			lock (_callbacks)
    27 			{
    28 				_callbacks.AddLast(item);
    29 			}
    30 			ThreadPool.QueueUserWorkItem(new WaitCallback(HandleItem));
    31 			return item;
    32 		}
    33 
    34 		private void HandleItem(object ignored)
    35 		{
    36 			WorkItem item = null;
    37 			try
    38 			{
    39 				lock (_callbacks)
    40 				{
    41 					if (_callbacks.Count > 0)
    42 					{
    43 						item = _callbacks.First.Value;
    44 						_callbacks.RemoveFirst();
    45 					}
    46 					if (item == null)
    47 						return;
    48 					_threads.Add(item, Thread.CurrentThread);
    49 
    50 				}
    51 				ExecutionContext.Run(item.Context,
    52 					delegate { item.Callback(item.State); }, null);
    53 			}
    54 			finally
    55 			{
    56 				lock (_callbacks)
    57 				{
    58 					if (item != null)
    59 						_threads.Remove(item);
    60 				}
    61 			}
    62 		}
    63 
    64 		public bool IsMyThread(Thread thread)
    65 		{
    66 			lock (_callbacks)
    67 			{
    68 				foreach (Thread t in _threads.Values)
    69 				{
    70 					if (t == thread)
    71 						return true;
    72 				}
    73 				return false;
    74 			}
    75 		}
    76 
    77 		public WorkItemStatus Cancel(WorkItem item, bool allowAbort)
    78 		{
    79 			if (item == null)
    80 				throw new ArgumentNullException("item");
    81 			lock (_callbacks)
    82 			{
    83 				LinkedListNode<WorkItem> node = _callbacks.Find(item);
    84 				if (node != null)
    85 				{
    86 					_callbacks.Remove(node);
    87 					return WorkItemStatus.Queued;
    88 				}
    89 				else if (_threads.ContainsKey(item))
    90 				{
    91 					if (allowAbort)
    92 					{
    93 						_threads[item].Abort();
    94 						_threads.Remove(item);
    95 						return WorkItemStatus.Aborted;
    96 					}
    97 					else
    98 						return WorkItemStatus.Executing;
    99 				}
   100 				else
   101 					return WorkItemStatus.Completed;
   102 			}
   103 		}
   104 
   105 		public void CancelAll(bool allowAbort)
   106 		{
   107 			lock (_callbacks)
   108 			{
   109 				_callbacks.Clear();
   110 				if (allowAbort)
   111 				{
   112 					foreach (Thread t in _threads.Values)
   113 						t.Abort();
   114 				}
   115 			}
   116 		}
   117 	}
   118 }