aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ThirdParty/SmartThreadPool/WorkItem.cs
diff options
context:
space:
mode:
authorTeravus Ovares2008-05-30 12:27:06 +0000
committerTeravus Ovares2008-05-30 12:27:06 +0000
commit1a47ff8094ee414a47aebd310826906d89428a09 (patch)
tree0e90b3a33f43ff8617a077bb57b86d6b28e63e71 /ThirdParty/SmartThreadPool/WorkItem.cs
parent* Fixed a dangling event hook that I added. (diff)
downloadopensim-SC_OLD-1a47ff8094ee414a47aebd310826906d89428a09.zip
opensim-SC_OLD-1a47ff8094ee414a47aebd310826906d89428a09.tar.gz
opensim-SC_OLD-1a47ff8094ee414a47aebd310826906d89428a09.tar.bz2
opensim-SC_OLD-1a47ff8094ee414a47aebd310826906d89428a09.tar.xz
* This is Melanie's XEngine script engine. I've not tested this real well, however, it's confirmed to compile and OpenSimulator to run successfully without this script engine active.
Diffstat (limited to 'ThirdParty/SmartThreadPool/WorkItem.cs')
-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}