X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2Fcorlib%2FSystem.Threading.Tasks%2FTask.cs;h=bb023257b4769978f0db08de9d5a5a4a03119811;hb=a0173a7e76ad48889ade46116e516731b170e7c5;hp=1ae5559957ee710ce4206daf00fb0532f1df6987;hpb=b86af4848657c5fa6041d0eefa47ac004dc54442;p=mono.git diff --git a/mcs/class/corlib/System.Threading.Tasks/Task.cs b/mcs/class/corlib/System.Threading.Tasks/Task.cs index 1ae5559957e..bb023257b47 100644 --- a/mcs/class/corlib/System.Threading.Tasks/Task.cs +++ b/mcs/class/corlib/System.Threading.Tasks/Task.cs @@ -182,8 +182,11 @@ namespace System.Threading.Tasks if (IsContinuation) throw new InvalidOperationException ("Start may not be called on a continuation task"); + if (IsPromise) + throw new InvalidOperationException ("Start may not be called on a promise-style task"); + SetupScheduler (scheduler); - Schedule (); + Schedule (true); } internal void SetupScheduler (TaskScheduler scheduler) @@ -208,10 +211,13 @@ namespace System.Threading.Tasks if (IsContinuation) throw new InvalidOperationException ("RunSynchronously may not be called on a continuation task"); - RunSynchronouslyCore (scheduler); + if (IsPromise) + throw new InvalidOperationException ("RunSynchronously may not be called on a promise-style task"); + + RunSynchronouslyCore (scheduler, true); } - internal void RunSynchronouslyCore (TaskScheduler scheduler) + internal void RunSynchronouslyCore (TaskScheduler scheduler, bool throwException) { SetupScheduler (scheduler); Status = TaskStatus.WaitingToRun; @@ -220,11 +226,16 @@ namespace System.Threading.Tasks if (scheduler.RunInline (this, false)) return; } catch (Exception inner) { - throw new TaskSchedulerException (inner); + var ex = new TaskSchedulerException (inner); + TrySetException (new AggregateException (ex), false, true); + if (throwException) + throw ex; + + return; } - Schedule (); - Wait (); + Schedule (throwException); + WaitCore (Timeout.Infinite, CancellationToken.None, false); } #endregion @@ -330,18 +341,27 @@ namespace System.Threading.Tasks ContinueWith (new TaskContinuation (continuation, options)); } - internal void ContinueWith (IContinuation continuation) + internal bool ContinueWith (IContinuation continuation, bool canExecuteInline = true) { if (IsCompleted) { + if (!canExecuteInline) + return false; + continuation.Execute (); - return; + return true; } continuations.Add (continuation); // Retry in case completion was achieved but event adding was too late - if (IsCompleted && continuations.Remove (continuation)) + if (IsCompleted && continuations.Remove (continuation)) { + if (!canExecuteInline) + return false; + continuation.Execute (); + } + + return true; } internal void RemoveContinuation (IContinuation continuation) @@ -364,10 +384,17 @@ namespace System.Threading.Tasks #endregion #region Internal and protected thingies - internal void Schedule () + internal void Schedule (bool throwException) { Status = TaskStatus.WaitingToRun; - scheduler.QueueTask (this); + try { + scheduler.QueueTask (this); + } catch (Exception inner) { + var ex = new TaskSchedulerException (inner); + TrySetException (new AggregateException (ex), false, true); + if (throwException) + throw ex; + } } void ThreadStart () @@ -438,7 +465,7 @@ namespace System.Threading.Tasks return true; } - internal bool TrySetException (AggregateException aggregate) + internal bool TrySetException (AggregateException aggregate, bool cancellation, bool observed) { if (IsCompleted) return false; @@ -450,8 +477,19 @@ namespace System.Threading.Tasks return false; } - - HandleGenericException (aggregate); + + if (cancellation) { + ExceptionSlot.Exception = aggregate; + Thread.MemoryBarrier (); + + CancelReal (); + } else { + HandleGenericException (aggregate); + } + + if (observed) + exSlot.Observed = true; + return true; } @@ -641,7 +679,7 @@ namespace System.Threading.Tasks if (millisecondsTimeout < -1) throw new ArgumentOutOfRangeException ("millisecondsTimeout"); - bool result = WaitCore (millisecondsTimeout, cancellationToken); + bool result = WaitCore (millisecondsTimeout, cancellationToken, true); if (IsCanceled) throw new AggregateException (new TaskCanceledException (this)); @@ -653,14 +691,19 @@ namespace System.Threading.Tasks return result; } - internal bool WaitCore (int millisecondsTimeout, CancellationToken cancellationToken) + internal bool WaitCore (int millisecondsTimeout, CancellationToken cancellationToken, bool runInline) { if (IsCompleted) return true; // If the task is ready to be run and we were supposed to wait on it indefinitely without cancellation, just run it - if (Status == TaskStatus.WaitingToRun && millisecondsTimeout == Timeout.Infinite && scheduler != null && !cancellationToken.CanBeCanceled) - scheduler.RunInline (this, true); + if (runInline && Status == TaskStatus.WaitingToRun && millisecondsTimeout == Timeout.Infinite && scheduler != null && !cancellationToken.CanBeCanceled) { + try { + scheduler.RunInline (this, true); + } catch (Exception e) { + throw new TaskSchedulerException (e); + } + } bool result = true; @@ -1082,6 +1125,9 @@ namespace System.Threading.Tasks internal static Task WhenAllCore (IList> tasks) { + if (tasks.Count == 0) + return FromResult(new TResult[0]); + foreach (var t in tasks) { if (t == null) throw new ArgumentException ("tasks", "the tasks argument contains a null element"); @@ -1242,7 +1288,7 @@ namespace System.Threading.Tasks public AggregateException Exception { get { - if (exSlot == null) + if (exSlot == null || !IsFaulted) return null; exSlot.Observed = true; return exSlot.Exception; @@ -1283,7 +1329,7 @@ namespace System.Threading.Tasks } } - TaskExceptionSlot ExceptionSlot { + internal TaskExceptionSlot ExceptionSlot { get { if (exSlot != null) return exSlot; @@ -1328,6 +1374,12 @@ namespace System.Threading.Tasks } } + bool IsPromise { + get { + return invoker == TaskActionInvoker.Promise; + } + } + internal Task ContinuationAncestor { get { return contAncestor;