aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ThirdParty/SmartThreadPool/WorkItem.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--ThirdParty/SmartThreadPool/WorkItem.cs1035
1 files changed, 1035 insertions, 0 deletions
diff --git a/ThirdParty/SmartThreadPool/WorkItem.cs b/ThirdParty/SmartThreadPool/WorkItem.cs
new file mode 100644
index 0000000..d0c0524
--- /dev/null
+++ b/ThirdParty/SmartThreadPool/WorkItem.cs
@@ -0,0 +1,1035 @@
1// Ami Bar
2// amibar@gmail.com
3
4using System;
5using System.Threading;
6using System.Diagnostics;
7
8namespace Amib.Threading.Internal
9{
10 #region WorkItem Delegate
11
12 /// <summary>
13 /// An internal delegate to call when the WorkItem starts or completes
14 /// </summary>
15 internal delegate void WorkItemStateCallback(WorkItem workItem);
16
17 #endregion
18
19 #region IInternalWorkItemResult interface
20
21 public class CanceledWorkItemsGroup
22 {
23 public readonly static CanceledWorkItemsGroup NotCanceledWorkItemsGroup = new CanceledWorkItemsGroup();
24
25 private bool _isCanceled = false;
26 public bool IsCanceled
27 {
28 get { return _isCanceled; }
29 set { _isCanceled = value; }
30 }
31 }
32
33 internal interface IInternalWorkItemResult
34 {
35 event WorkItemStateCallback OnWorkItemStarted;
36 event WorkItemStateCallback OnWorkItemCompleted;
37 }
38
39 #endregion
40
41 #region IWorkItem interface
42
43 public interface IWorkItem
44 {
45
46 }
47
48 #endregion
49
50 #region WorkItem class
51
52 /// <summary>
53 /// Holds a callback delegate and the state for that delegate.
54 /// </summary>
55 public class WorkItem : IHasWorkItemPriority, IWorkItem
56 {
57 #region WorkItemState enum
58
59 /// <summary>
60 /// Indicates the state of the work item in the thread pool
61 /// </summary>
62 private enum WorkItemState
63 {
64 InQueue,
65 InProgress,
66 Completed,
67 Canceled,
68 }
69
70 #endregion
71
72 #region Member Variables
73
74 public Thread currentThread;
75
76 /// <summary>
77 /// Callback delegate for the callback.
78 /// </summary>
79 private WorkItemCallback _callback;
80
81 /// <summary>
82 /// State with which to call the callback delegate.
83 /// </summary>
84 private object _state;
85
86 /// <summary>
87 /// Stores the caller's context
88 /// </summary>
89 private CallerThreadContext _callerContext;
90
91 /// <summary>
92 /// Holds the result of the mehtod
93 /// </summary>
94 private object _result;
95
96 /// <summary>
97 /// Hold the exception if the method threw it
98 /// </summary>
99 private Exception _exception;
100
101 /// <summary>
102 /// Hold the state of the work item
103 /// </summary>
104 private WorkItemState _workItemState;
105
106 /// <summary>
107 /// A ManualResetEvent to indicate that the result is ready
108 /// </summary>
109 private ManualResetEvent _workItemCompleted;
110
111 /// <summary>
112 /// A reference count to the _workItemCompleted.
113 /// When it reaches to zero _workItemCompleted is Closed
114 /// </summary>
115 private int _workItemCompletedRefCount;
116
117 /// <summary>
118 /// Represents the result state of the work item
119 /// </summary>
120 private WorkItemResult _workItemResult;
121
122 /// <summary>
123 /// Work item info
124 /// </summary>
125 private WorkItemInfo _workItemInfo;
126
127 /// <summary>
128 /// Called when the WorkItem starts
129 /// </summary>
130 private event WorkItemStateCallback _workItemStartedEvent;
131
132 /// <summary>
133 /// Called when the WorkItem completes
134 /// </summary>
135 private event WorkItemStateCallback _workItemCompletedEvent;
136
137 /// <summary>
138 /// A reference to an object that indicates whatever the
139 /// WorkItemsGroup has been canceled
140 /// </summary>
141 private CanceledWorkItemsGroup _canceledWorkItemsGroup = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup;
142
143 /// <summary>
144 /// The work item group this work item belong to.
145 ///
146 /// </summary>
147 private IWorkItemsGroup _workItemsGroup;
148
149 #region Performance Counter fields
150
151 /// <summary>
152 /// The time when the work items is queued.
153 /// Used with the performance counter.
154 /// </summary>
155 private DateTime _queuedTime;
156
157 /// <summary>
158 /// The time when the work items starts its execution.
159 /// Used with the performance counter.
160 /// </summary>
161 private DateTime _beginProcessTime;
162
163 /// <summary>
164 /// The time when the work items ends its execution.
165 /// Used with the performance counter.
166 /// </summary>
167 private DateTime _endProcessTime;
168
169 #endregion
170
171 #endregion
172
173 #region Properties
174
175 public TimeSpan WaitingTime
176 {
177 get
178 {
179 return (_beginProcessTime - _queuedTime);
180 }
181 }
182
183 public TimeSpan ProcessTime
184 {
185 get
186 {
187 return (_endProcessTime - _beginProcessTime);
188 }
189 }
190
191 #endregion
192
193 #region Construction
194
195 /// <summary>
196 /// Initialize the callback holding object.
197 /// </summary>
198 /// <param name="callback">Callback delegate for the callback.</param>
199 /// <param name="state">State with which to call the callback delegate.</param>
200 ///
201 /// We assume that the WorkItem object is created within the thread
202 /// that meant to run the callback
203 public WorkItem(
204 IWorkItemsGroup workItemsGroup,
205 WorkItemInfo workItemInfo,
206 WorkItemCallback callback,
207 object state)
208 {
209 _workItemsGroup = workItemsGroup;
210 _workItemInfo = workItemInfo;
211
212 if (_workItemInfo.UseCallerCallContext || _workItemInfo.UseCallerHttpContext)
213 {
214 _callerContext = CallerThreadContext.Capture(_workItemInfo.UseCallerCallContext, _workItemInfo.UseCallerHttpContext);
215 }
216
217 _callback = callback;
218 _state = state;
219 _workItemResult = new WorkItemResult(this);
220 Initialize();
221 }
222
223 internal void Initialize()
224 {
225 _workItemState = WorkItemState.InQueue;
226 _workItemCompleted = null;
227 _workItemCompletedRefCount = 0;
228 }
229
230 internal bool WasQueuedBy(IWorkItemsGroup workItemsGroup)
231 {
232 return (workItemsGroup == _workItemsGroup);
233 }
234
235
236 #endregion
237
238 #region Methods
239
240 public CanceledWorkItemsGroup CanceledWorkItemsGroup
241 {
242 get
243 {
244 return _canceledWorkItemsGroup;
245 }
246
247 set
248 {
249 _canceledWorkItemsGroup = value;
250 }
251 }
252
253 /// <summary>
254 /// Change the state of the work item to in progress if it wasn't canceled.
255 /// </summary>
256 /// <returns>
257 /// Return true on success or false in case the work item was canceled.
258 /// If the work item needs to run a post execute then the method will return true.
259 /// </returns>
260 public bool StartingWorkItem()
261 {
262 _beginProcessTime = DateTime.Now;
263
264 lock(this)
265 {
266 if (IsCanceled)
267 {
268 bool result = false;
269 if ((_workItemInfo.PostExecuteWorkItemCallback != null) &&
270 ((_workItemInfo.CallToPostExecute & CallToPostExecute.WhenWorkItemCanceled) == CallToPostExecute.WhenWorkItemCanceled))
271 {
272 result = true;
273 }
274
275 return result;
276 }
277
278 Debug.Assert(WorkItemState.InQueue == GetWorkItemState());
279
280 SetWorkItemState(WorkItemState.InProgress);
281 }
282
283 return true;
284 }
285
286 /// <summary>
287 /// Execute the work item and the post execute
288 /// </summary>
289 public void Execute()
290 {
291 CallToPostExecute currentCallToPostExecute = 0;
292
293 // Execute the work item if we are in the correct state
294 switch(GetWorkItemState())
295 {
296 case WorkItemState.InProgress:
297 currentCallToPostExecute |= CallToPostExecute.WhenWorkItemNotCanceled;
298 ExecuteWorkItem();
299 break;
300 case WorkItemState.Canceled:
301 currentCallToPostExecute |= CallToPostExecute.WhenWorkItemCanceled;
302 break;
303 default:
304 Debug.Assert(false);
305 throw new NotSupportedException();
306 }
307
308 // Run the post execute as needed
309 if ((currentCallToPostExecute & _workItemInfo.CallToPostExecute) != 0)
310 {
311 PostExecute();
312 }
313
314 _endProcessTime = DateTime.Now;
315 }
316
317 internal void FireWorkItemCompleted()
318 {
319 try
320 {
321 if (null != _workItemCompletedEvent)
322 {
323 _workItemCompletedEvent(this);
324 }
325 }
326 catch // Ignore exceptions
327 {}
328 }
329
330 /// <summary>
331 /// Execute the work item
332 /// </summary>
333 private void ExecuteWorkItem()
334 {
335 CallerThreadContext ctc = null;
336 if (null != _callerContext)
337 {
338 ctc = CallerThreadContext.Capture(_callerContext.CapturedCallContext, _callerContext.CapturedHttpContext);
339 CallerThreadContext.Apply(_callerContext);
340 }
341
342 Exception exception = null;
343 object result = null;
344
345 try
346 {
347 result = _callback(_state);
348 }
349 catch (Exception e)
350 {
351 // Save the exception so we can rethrow it later
352 exception = e;
353 }
354
355 if (null != _callerContext)
356 {
357 CallerThreadContext.Apply(ctc);
358 }
359
360 SetResult(result, exception);
361 }
362
363 /// <summary>
364 /// Runs the post execute callback
365 /// </summary>
366 private void PostExecute()
367 {
368 if (null != _workItemInfo.PostExecuteWorkItemCallback)
369 {
370 try
371 {
372 _workItemInfo.PostExecuteWorkItemCallback(this._workItemResult);
373 }
374 catch (Exception e)
375 {
376 Debug.Assert(null != e);
377 }
378 }
379 }
380
381 /// <summary>
382 /// Set the result of the work item to return
383 /// </summary>
384 /// <param name="result">The result of the work item</param>
385 internal void SetResult(object result, Exception exception)
386 {
387 _result = result;
388 _exception = exception;
389 SignalComplete(false);
390 }
391
392 /// <summary>
393 /// Returns the work item result
394 /// </summary>
395 /// <returns>The work item result</returns>
396 internal IWorkItemResult GetWorkItemResult()
397 {
398 return _workItemResult;
399 }
400
401 /// <summary>
402 /// Wait for all work items to complete
403 /// </summary>
404 /// <param name="workItemResults">Array of work item result objects</param>
405 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
406 /// <param name="exitContext">
407 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
408 /// </param>
409 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
410 /// <returns>
411 /// true when every work item in workItemResults has completed; otherwise false.
412 /// </returns>
413 internal static bool WaitAll(
414 IWorkItemResult [] workItemResults,
415 int millisecondsTimeout,
416 bool exitContext,
417 WaitHandle cancelWaitHandle)
418 {
419 if (0 == workItemResults.Length)
420 {
421 return true;
422 }
423
424 bool success;
425 WaitHandle [] waitHandles = new WaitHandle[workItemResults.Length];;
426 GetWaitHandles(workItemResults, waitHandles);
427
428 if ((null == cancelWaitHandle) && (waitHandles.Length <= 64))
429 {
430 success = WaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
431 }
432 else
433 {
434 success = true;
435 int millisecondsLeft = millisecondsTimeout;
436 DateTime start = DateTime.Now;
437
438 WaitHandle [] whs;
439 if (null != cancelWaitHandle)
440 {
441 whs = new WaitHandle [] { null, cancelWaitHandle };
442 }
443 else
444 {
445 whs = new WaitHandle [] { null };
446 }
447
448 bool waitInfinitely = (Timeout.Infinite == millisecondsTimeout);
449 // Iterate over the wait handles and wait for each one to complete.
450 // We cannot use WaitHandle.WaitAll directly, because the cancelWaitHandle
451 // won't affect it.
452 // Each iteration we update the time left for the timeout.
453 for(int i = 0; i < workItemResults.Length; ++i)
454 {
455 // WaitAny don't work with negative numbers
456 if (!waitInfinitely && (millisecondsLeft < 0))
457 {
458 success = false;
459 break;
460 }
461
462 whs[0] = waitHandles[i];
463 int result = WaitHandle.WaitAny(whs, millisecondsLeft, exitContext);
464 if((result > 0) || (WaitHandle.WaitTimeout == result))
465 {
466 success = false;
467 break;
468 }
469
470 if(!waitInfinitely)
471 {
472 // Update the time left to wait
473 TimeSpan ts = DateTime.Now - start;
474 millisecondsLeft = millisecondsTimeout - (int)ts.TotalMilliseconds;
475 }
476 }
477 }
478 // Release the wait handles
479 ReleaseWaitHandles(workItemResults);
480
481 return success;
482 }
483
484 /// <summary>
485 /// Waits for any of the work items in the specified array to complete, cancel, or timeout
486 /// </summary>
487 /// <param name="workItemResults">Array of work item result objects</param>
488 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
489 /// <param name="exitContext">
490 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
491 /// </param>
492 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
493 /// <returns>
494 /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled.
495 /// </returns>
496 internal static int WaitAny(
497 IWorkItemResult [] workItemResults,
498 int millisecondsTimeout,
499 bool exitContext,
500 WaitHandle cancelWaitHandle)
501 {
502 WaitHandle [] waitHandles = null;
503
504 if (null != cancelWaitHandle)
505 {
506 waitHandles = new WaitHandle[workItemResults.Length+1];
507 GetWaitHandles(workItemResults, waitHandles);
508 waitHandles[workItemResults.Length] = cancelWaitHandle;
509 }
510 else
511 {
512 waitHandles = new WaitHandle[workItemResults.Length];
513 GetWaitHandles(workItemResults, waitHandles);
514 }
515
516 int result = WaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext);
517
518 // Treat cancel as timeout
519 if (null != cancelWaitHandle)
520 {
521 if (result == workItemResults.Length)
522 {
523 result = WaitHandle.WaitTimeout;
524 }
525 }
526
527 ReleaseWaitHandles(workItemResults);
528
529 return result;
530 }
531
532 /// <summary>
533 /// Fill an array of wait handles with the work items wait handles.
534 /// </summary>
535 /// <param name="workItemResults">An array of work item results</param>
536 /// <param name="waitHandles">An array of wait handles to fill</param>
537 private static void GetWaitHandles(
538 IWorkItemResult [] workItemResults,
539 WaitHandle [] waitHandles)
540 {
541 for(int i = 0; i < workItemResults.Length; ++i)
542 {
543 WorkItemResult wir = workItemResults[i] as WorkItemResult;
544 Debug.Assert(null != wir, "All workItemResults must be WorkItemResult objects");
545
546 waitHandles[i] = wir.GetWorkItem().GetWaitHandle();
547 }
548 }
549
550 /// <summary>
551 /// Release the work items' wait handles
552 /// </summary>
553 /// <param name="workItemResults">An array of work item results</param>
554 private static void ReleaseWaitHandles(IWorkItemResult [] workItemResults)
555 {
556 for(int i = 0; i < workItemResults.Length; ++i)
557 {
558 WorkItemResult wir = workItemResults[i] as WorkItemResult;
559
560 wir.GetWorkItem().ReleaseWaitHandle();
561 }
562 }
563
564
565 #endregion
566
567 #region Private Members
568
569 private WorkItemState GetWorkItemState()
570 {
571 if (_canceledWorkItemsGroup.IsCanceled)
572 {
573 return WorkItemState.Canceled;
574 }
575 return _workItemState;
576
577 }
578 /// <summary>
579 /// Sets the work item's state
580 /// </summary>
581 /// <param name="workItemState">The state to set the work item to</param>
582 private void SetWorkItemState(WorkItemState workItemState)
583 {
584 lock(this)
585 {
586 _workItemState = workItemState;
587 }
588 }
589
590 /// <summary>
591 /// Signals that work item has been completed or canceled
592 /// </summary>
593 /// <param name="canceled">Indicates that the work item has been canceled</param>
594 private void SignalComplete(bool canceled)
595 {
596 SetWorkItemState(canceled ? WorkItemState.Canceled : WorkItemState.Completed);
597 lock(this)
598 {
599 // If someone is waiting then signal.
600 if (null != _workItemCompleted)
601 {
602 _workItemCompleted.Set();
603 }
604 }
605 }
606
607 internal void WorkItemIsQueued()
608 {
609 _queuedTime = DateTime.Now;
610 }
611
612 #endregion
613
614 #region Members exposed by WorkItemResult
615
616 /// <summary>
617 /// Cancel the work item if it didn't start running yet.
618 /// </summary>
619 /// <returns>Returns true on success or false if the work item is in progress or already completed</returns>
620 private bool Cancel()
621 {
622 lock(this)
623 {
624 switch(GetWorkItemState())
625 {
626 case WorkItemState.Canceled:
627 //Debug.WriteLine("Work item already canceled");
628 return true;
629 case WorkItemState.Completed:
630 case WorkItemState.InProgress:
631 //Debug.WriteLine("Work item cannot be canceled");
632 return false;
633 case WorkItemState.InQueue:
634 // Signal to the wait for completion that the work
635 // item has been completed (canceled). There is no
636 // reason to wait for it to get out of the queue
637 SignalComplete(true);
638 //Debug.WriteLine("Work item canceled");
639 return true;
640 }
641 }
642 return false;
643 }
644
645 /// <summary>
646 /// Get the result of the work item.
647 /// If the work item didn't run yet then the caller waits for the result, timeout, or cancel.
648 /// In case of error the method throws and exception
649 /// </summary>
650 /// <returns>The result of the work item</returns>
651 private object GetResult(
652 int millisecondsTimeout,
653 bool exitContext,
654 WaitHandle cancelWaitHandle)
655 {
656 Exception e = null;
657 object result = GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out e);
658 if (null != e)
659 {
660 throw new WorkItemResultException("The work item caused an excpetion, see the inner exception for details", e);
661 }
662 return result;
663 }
664
665 /// <summary>
666 /// Get the result of the work item.
667 /// If the work item didn't run yet then the caller waits for the result, timeout, or cancel.
668 /// In case of error the e argument is filled with the exception
669 /// </summary>
670 /// <returns>The result of the work item</returns>
671 private object GetResult(
672 int millisecondsTimeout,
673 bool exitContext,
674 WaitHandle cancelWaitHandle,
675 out Exception e)
676 {
677 e = null;
678
679 // Check for cancel
680 if (WorkItemState.Canceled == GetWorkItemState())
681 {
682 throw new WorkItemCancelException("Work item canceled");
683 }
684
685 // Check for completion
686 if (IsCompleted)
687 {
688 e = _exception;
689 return _result;
690 }
691
692 // If no cancelWaitHandle is provided
693 if (null == cancelWaitHandle)
694 {
695 WaitHandle wh = GetWaitHandle();
696
697 bool timeout = !wh.WaitOne(millisecondsTimeout, exitContext);
698
699 ReleaseWaitHandle();
700
701 if (timeout)
702 {
703 throw new WorkItemTimeoutException("Work item timeout");
704 }
705 }
706 else
707 {
708 WaitHandle wh = GetWaitHandle();
709 int result = WaitHandle.WaitAny(new WaitHandle[] { wh, cancelWaitHandle });
710 ReleaseWaitHandle();
711
712 switch(result)
713 {
714 case 0:
715 // The work item signaled
716 // Note that the signal could be also as a result of canceling the
717 // work item (not the get result)
718 break;
719 case 1:
720 case WaitHandle.WaitTimeout:
721 throw new WorkItemTimeoutException("Work item timeout");
722 default:
723 Debug.Assert(false);
724 break;
725
726 }
727 }
728
729 // Check for cancel
730 if (WorkItemState.Canceled == GetWorkItemState())
731 {
732 throw new WorkItemCancelException("Work item canceled");
733 }
734
735 Debug.Assert(IsCompleted);
736
737 e = _exception;
738
739 // Return the result
740 return _result;
741 }
742
743 /// <summary>
744 /// A wait handle to wait for completion, cancel, or timeout
745 /// </summary>
746 private WaitHandle GetWaitHandle()
747 {
748 lock(this)
749 {
750 if (null == _workItemCompleted)
751 {
752 _workItemCompleted = new ManualResetEvent(IsCompleted);
753 }
754 ++_workItemCompletedRefCount;
755 }
756 return _workItemCompleted;
757 }
758
759 private void ReleaseWaitHandle()
760 {
761 lock(this)
762 {
763 if (null != _workItemCompleted)
764 {
765 --_workItemCompletedRefCount;
766 if (0 == _workItemCompletedRefCount)
767 {
768 _workItemCompleted.Close();
769 _workItemCompleted = null;
770 }
771 }
772 }
773 }
774
775 /// <summary>
776 /// Returns true when the work item has completed or canceled
777 /// </summary>
778 private bool IsCompleted
779 {
780 get
781 {
782 lock(this)
783 {
784 WorkItemState workItemState = GetWorkItemState();
785 return ((workItemState == WorkItemState.Completed) ||
786 (workItemState == WorkItemState.Canceled));
787 }
788 }
789 }
790
791 /// <summary>
792 /// Returns true when the work item has canceled
793 /// </summary>
794 public bool IsCanceled
795 {
796 get
797 {
798 lock(this)
799 {
800 return (GetWorkItemState() == WorkItemState.Canceled);
801 }
802 }
803 }
804
805 #endregion
806
807 #region IHasWorkItemPriority Members
808
809 /// <summary>
810 /// Returns the priority of the work item
811 /// </summary>
812 public WorkItemPriority WorkItemPriority
813 {
814 get
815 {
816 return _workItemInfo.WorkItemPriority;
817 }
818 }
819
820 #endregion
821
822 internal event WorkItemStateCallback OnWorkItemStarted
823 {
824 add
825 {
826 _workItemStartedEvent += value;
827 }
828 remove
829 {
830 _workItemStartedEvent -= value;
831 }
832 }
833
834 internal event WorkItemStateCallback OnWorkItemCompleted
835 {
836 add
837 {
838 _workItemCompletedEvent += value;
839 }
840 remove
841 {
842 _workItemCompletedEvent -= value;
843 }
844 }
845
846
847 #region WorkItemResult class
848
849 private class WorkItemResult : IWorkItemResult, IInternalWorkItemResult
850 {
851 /// <summary>
852 /// A back reference to the work item
853 /// </summary>
854 private WorkItem _workItem;
855
856 public WorkItemResult(WorkItem workItem)
857 {
858 _workItem = workItem;
859 }
860
861 internal WorkItem GetWorkItem()
862 {
863 return _workItem;
864 }
865
866 #region IWorkItemResult Members
867
868 public bool IsCompleted
869 {
870 get
871 {
872 return _workItem.IsCompleted;
873 }
874 }
875
876 public void Abort()
877 {
878 _workItem.Abort();
879 }
880
881 public bool IsCanceled
882 {
883 get
884 {
885 return _workItem.IsCanceled;
886 }
887 }
888
889 public object GetResult()
890 {
891 return _workItem.GetResult(Timeout.Infinite, true, null);
892 }
893
894 public object GetResult(int millisecondsTimeout, bool exitContext)
895 {
896 return _workItem.GetResult(millisecondsTimeout, exitContext, null);
897 }
898
899 public object GetResult(TimeSpan timeout, bool exitContext)
900 {
901 return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, null);
902 }
903
904 public object GetResult(int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle)
905 {
906 return _workItem.GetResult(millisecondsTimeout, exitContext, cancelWaitHandle);
907 }
908
909 public object GetResult(TimeSpan timeout, bool exitContext, WaitHandle cancelWaitHandle)
910 {
911 return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle);
912 }
913
914 public object GetResult(out Exception e)
915 {
916 return _workItem.GetResult(Timeout.Infinite, true, null, out e);
917 }
918
919 public object GetResult(int millisecondsTimeout, bool exitContext, out Exception e)
920 {
921 return _workItem.GetResult(millisecondsTimeout, exitContext, null, out e);
922 }
923
924 public object GetResult(TimeSpan timeout, bool exitContext, out Exception e)
925 {
926 return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, null, out e);
927 }
928
929 public object GetResult(int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle, out Exception e)
930 {
931 return _workItem.GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out e);
932 }
933
934 public object GetResult(TimeSpan timeout, bool exitContext, WaitHandle cancelWaitHandle, out Exception e)
935 {
936 return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle, out e);
937 }
938
939 public bool Cancel()
940 {
941 return _workItem.Cancel();
942 }
943
944 public object State
945 {
946 get
947 {
948 return _workItem._state;
949 }
950 }
951
952 public WorkItemPriority WorkItemPriority
953 {
954 get
955 {
956 return _workItem._workItemInfo.WorkItemPriority;
957 }
958 }
959
960 /// <summary>
961 /// Return the result, same as GetResult()
962 /// </summary>
963 public object Result
964 {
965 get { return GetResult(); }
966 }
967
968 /// <summary>
969 /// Returns the exception if occured otherwise returns null.
970 /// This value is valid only after the work item completed,
971 /// before that it is always null.
972 /// </summary>
973 public object Exception
974 {
975 get { return _workItem._exception; }
976 }
977
978 #endregion
979
980 #region IInternalWorkItemResult Members
981
982 public event WorkItemStateCallback OnWorkItemStarted
983 {
984 add
985 {
986 _workItem.OnWorkItemStarted += value;
987 }
988 remove
989 {
990 _workItem.OnWorkItemStarted -= value;
991 }
992 }
993
994
995 public event WorkItemStateCallback OnWorkItemCompleted
996 {
997 add
998 {
999 _workItem.OnWorkItemCompleted += value;
1000 }
1001 remove
1002 {
1003 _workItem.OnWorkItemCompleted -= value;
1004 }
1005 }
1006
1007 #endregion
1008 }
1009
1010 #endregion
1011
1012 public void DisposeOfState()
1013 {
1014 if (_workItemInfo.DisposeOfStateObjects)
1015 {
1016 IDisposable disp = _state as IDisposable;
1017 if (null != disp)
1018 {
1019 disp.Dispose();
1020 _state = null;
1021 }
1022 }
1023 }
1024
1025 public void Abort()
1026 {
1027 lock (this)
1028 {
1029 if(currentThread != null)
1030 currentThread.Abort();
1031 }
1032 }
1033 }
1034 #endregion
1035}