External/Aga.Controls/Threading/AbortableThreadPool.cs
author StephaneLenclud
Sun, 03 Feb 2013 18:01:50 +0100
branchMiniDisplay
changeset 433 090259cfd699
permissions -rw-r--r--
Adding SoundGraphDisplay and SensorFrontView classes.
They were respectively based on SystemTray and SensorNotifyIcon.
SoundGraphDisplay is now able to load iMONDisplay.dll providing it lives on your PATH.
Adding option to sensor context menu for adding it into FrontView.
     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 }