ConcurrentQueue<AggregateException> childExceptions;
TaskStatus status;
-
- Action<object> action;
- Action simpleAction;
+
+ TaskActionInvoker invoker;
object state;
AtomicBooleanValue executing;
#endif
TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent;
- public Task (Action action) : this (action, TaskCreationOptions.None)
+ public Task (Action action)
+ : this (action, TaskCreationOptions.None)
{
}
- public Task (Action action, TaskCreationOptions creationOptions) : this (action, CancellationToken.None, creationOptions)
+ public Task (Action action, TaskCreationOptions creationOptions)
+ : this (action, CancellationToken.None, creationOptions)
{
}
- public Task (Action action, CancellationToken cancellationToken) : this (action, cancellationToken, TaskCreationOptions.None)
+ public Task (Action action, CancellationToken cancellationToken)
+ : this (action, cancellationToken, TaskCreationOptions.None)
{
}
public Task (Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
- : this (null, null, cancellationToken, creationOptions, current)
+ : this (TaskActionInvoker.Create (action), null, cancellationToken, creationOptions, current)
{
if (action == null)
throw new ArgumentNullException ("action");
if (creationOptions > MaxTaskCreationOptions || creationOptions < TaskCreationOptions.None)
throw new ArgumentOutOfRangeException ("creationOptions");
- this.simpleAction = action;
}
- public Task (Action<object> action, object state) : this (action, state, TaskCreationOptions.None)
+ public Task (Action<object> action, object state)
+ : this (action, state, TaskCreationOptions.None)
{
}
}
public Task (Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
- : this (action, state, cancellationToken, creationOptions, current)
+ : this (TaskActionInvoker.Create (action), state, cancellationToken, creationOptions, current)
{
if (action == null)
throw new ArgumentNullException ("action");
throw new ArgumentOutOfRangeException ("creationOptions");
}
- internal Task (Action<object> action,
- object state,
- CancellationToken cancellationToken,
- TaskCreationOptions creationOptions,
- Task parent)
+ internal Task (TaskActionInvoker invoker, object state, CancellationToken cancellationToken,
+ TaskCreationOptions creationOptions, Task parent)
{
+ this.invoker = invoker;
this.taskCreationOptions = creationOptions;
- this.action = action;
this.state = state;
this.taskId = Interlocked.Increment (ref id);
this.status = cancellationToken.IsCancellationRequested ? TaskStatus.Canceled : TaskStatus.Created;
if (status >= TaskStatus.WaitingToRun)
throw new InvalidOperationException ("The Task is not in a valid state to be started.");
- if (Slot.Initialized)
+ if (IsContinuation)
throw new InvalidOperationException ("Start may not be called on a continuation task");
SetupScheduler (scheduler);
if (scheduler == null)
throw new ArgumentNullException ("scheduler");
- Task continuation = new Task (l => continuationAction ((Task)l),
- this,
+ Task continuation = new Task (TaskActionInvoker.Create (continuationAction),
+ null,
cancellationToken,
GetCreationOptions (continuationOptions),
this);
if (scheduler == null)
throw new ArgumentNullException ("scheduler");
- Task<TResult> t = new Task<TResult> ((o) => continuationFunction ((Task)o),
- this,
+ var t = new Task<TResult> (TaskActionInvoker.Create (continuationFunction),
+ null,
cancellationToken,
GetCreationOptions (continuationOptions),
this);
}
}
- internal virtual void InnerInvoke ()
+ void InnerInvoke ()
{
- if (action == null && simpleAction != null)
- simpleAction ();
- else if (action != null)
- action (state);
- // Set action to null so that the GC can collect the delegate and thus
- // any big object references that the user might have captured in an anonymous method
- action = null;
- simpleAction = null;
- state = null;
+ if (IsContinuation) {
+ invoker.Invoke (parent, state, this);
+ } else {
+ invoker.Invoke (this, state, this);
+ }
}
internal void Finish ()
// Set action to null so that the GC can collect the delegate and thus
// any big object references that the user might have captured in a anonymous method
if (disposing) {
- action = null;
+ invoker = null;
state = null;
if (cancellationRegistration != null)
cancellationRegistration.Value.Dispose ();
if (scheduler == null)
throw new ArgumentNullException ("scheduler");
- Task continuation = new Task (l => continuationAction (this, l), state,
- cancellationToken,
+ Task continuation = new Task (TaskActionInvoker.Create (continuationAction),
+ state, cancellationToken,
GetCreationOptions (continuationOptions),
this);
ContinueWithCore (continuation, continuationOptions, scheduler);
if (scheduler == null)
throw new ArgumentNullException ("scheduler");
- var t = new Task<TResult> (l => continuationFunction (this, l),
+ var t = new Task<TResult> (TaskActionInvoker.Create (continuationFunction),
state,
cancellationToken,
GetCreationOptions (continuationOptions),
}
}
+ bool IsContinuation {
+ get {
+ return Slot.Initialized;
+ }
+ }
+
internal Task Parent {
get {
return parent;
internal string DisplayActionMethod {
get {
- Delegate d = simpleAction ?? (Delegate) action;
+ Delegate d = invoker.Action;
return d == null ? "<none>" : d.Method.ToString ();
}
}
--- /dev/null
+//
+// TaskActionInvoker.cs
+//
+// Authors:
+// Marek Safar <marek.safar@gmail.com>
+//
+// Copyright 2011 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+//
+
+#if NET_4_0 || MOBILE
+
+namespace System.Threading.Tasks
+{
+ abstract class TaskActionInvoker
+ {
+ sealed class ActionInvoke : TaskActionInvoker
+ {
+ readonly Action action;
+
+ public ActionInvoke (Action action)
+ {
+ this.action = action;
+ }
+
+ public override Delegate Action {
+ get {
+ return action;
+ }
+ }
+
+ public override void Invoke (Task owner, object state, Task context)
+ {
+ action ();
+ }
+ }
+
+ sealed class ActionObjectInvoke : TaskActionInvoker
+ {
+ readonly Action<object> action;
+
+ public ActionObjectInvoke (Action<object> action)
+ {
+ this.action = action;
+ }
+
+ public override Delegate Action {
+ get {
+ return action;
+ }
+ }
+
+ public override void Invoke (Task owner, object state, Task context)
+ {
+ action (state);
+ }
+ }
+
+ sealed class ActionTaskInvoke : TaskActionInvoker
+ {
+ readonly Action<Task> action;
+
+ public ActionTaskInvoke (Action<Task> action)
+ {
+ this.action = action;
+ }
+
+ public override Delegate Action {
+ get {
+ return action;
+ }
+ }
+
+ public override void Invoke (Task owner, object state, Task context)
+ {
+ action (owner);
+ }
+ }
+
+ sealed class ActionTaskObjectInvoke : TaskActionInvoker
+ {
+ readonly Action<Task, object> action;
+
+ public ActionTaskObjectInvoke (Action<Task, object> action)
+ {
+ this.action = action;
+ }
+
+ public override Delegate Action {
+ get {
+ return action;
+ }
+ }
+
+ public override void Invoke (Task owner, object state, Task context)
+ {
+ action (owner, state);
+ }
+ }
+
+ sealed class ActionTaskObjectInvoke<TResult> : TaskActionInvoker
+ {
+ readonly Action<Task<TResult>, object> action;
+
+ public ActionTaskObjectInvoke (Action<Task<TResult>, object> action)
+ {
+ this.action = action;
+ }
+
+ public override Delegate Action {
+ get {
+ return action;
+ }
+ }
+
+ public override void Invoke (Task owner, object state, Task context)
+ {
+ action ((Task<TResult>) owner, state);
+ }
+ }
+
+ sealed class ActionTaskInvoke<TResult> : TaskActionInvoker
+ {
+ readonly Action<Task<TResult>> action;
+
+ public ActionTaskInvoke (Action<Task<TResult>> action)
+ {
+ this.action = action;
+ }
+
+ public override Delegate Action {
+ get {
+ return action;
+ }
+ }
+
+ public override void Invoke (Task owner, object state, Task context)
+ {
+ action ((Task<TResult>) owner);
+ }
+ }
+
+ sealed class FuncInvoke<TResult> : TaskActionInvoker
+ {
+ readonly Func<TResult> action;
+
+ public FuncInvoke (Func<TResult> action)
+ {
+ this.action = action;
+ }
+
+ public override Delegate Action {
+ get {
+ return action;
+ }
+ }
+
+ public override void Invoke (Task owner, object state, Task context)
+ {
+ ((Task<TResult>) context).Result = action ();
+ }
+ }
+
+ sealed class FuncTaskInvoke<TResult> : TaskActionInvoker
+ {
+ readonly Func<Task, TResult> action;
+
+ public FuncTaskInvoke (Func<Task, TResult> action)
+ {
+ this.action = action;
+ }
+
+ public override Delegate Action {
+ get {
+ return action;
+ }
+ }
+
+ public override void Invoke (Task owner, object state, Task context)
+ {
+ ((Task<TResult>) context).Result = action (owner);
+ }
+ }
+
+ sealed class FuncTaskInvoke<TResult, TNewResult> : TaskActionInvoker
+ {
+ readonly Func<Task<TResult>, TNewResult> action;
+
+ public FuncTaskInvoke (Func<Task<TResult>, TNewResult> action)
+ {
+ this.action = action;
+ }
+
+ public override Delegate Action {
+ get {
+ return action;
+ }
+ }
+
+ public override void Invoke (Task owner, object state, Task context)
+ {
+ ((Task<TNewResult>) context).Result = action ((Task<TResult>) owner);
+ }
+ }
+
+ sealed class FuncObjectInvoke<TResult> : TaskActionInvoker
+ {
+ readonly Func<object, TResult> action;
+
+ public FuncObjectInvoke (Func<object, TResult> action)
+ {
+ this.action = action;
+ }
+
+ public override Delegate Action {
+ get {
+ return action;
+ }
+ }
+
+ public override void Invoke (Task owner, object state, Task context)
+ {
+ ((Task<TResult>) context).Result = action (state);
+ }
+ }
+
+ sealed class FuncTaskObjectInvoke<TResult> : TaskActionInvoker
+ {
+ readonly Func<Task, object, TResult> action;
+
+ public FuncTaskObjectInvoke (Func<Task, object, TResult> action)
+ {
+ this.action = action;
+ }
+
+ public override Delegate Action {
+ get {
+ return action;
+ }
+ }
+
+ public override void Invoke (Task owner, object state, Task context)
+ {
+ ((Task<TResult>) context).Result = action (owner, state);
+ }
+ }
+
+ sealed class FuncTaskObjectInvoke<TResult, TNewResult> : TaskActionInvoker
+ {
+ readonly Func<Task<TResult>, object, TNewResult> action;
+
+ public FuncTaskObjectInvoke (Func<Task<TResult>, object, TNewResult> action)
+ {
+ this.action = action;
+ }
+
+ public override Delegate Action {
+ get {
+ return action;
+ }
+ }
+
+ public override void Invoke (Task owner, object state, Task context)
+ {
+ ((Task<TNewResult>) context).Result = action ((Task<TResult>) owner, state);
+ }
+ }
+
+ public static TaskActionInvoker Create (Action action)
+ {
+ return new ActionInvoke (action);
+ }
+
+ public static TaskActionInvoker Create (Action<object> action)
+ {
+ return new ActionObjectInvoke (action);
+ }
+
+ public static TaskActionInvoker Create (Action<Task> action)
+ {
+ return new ActionTaskInvoke (action);
+ }
+
+ public static TaskActionInvoker Create (Action<Task, object> action)
+ {
+ return new ActionTaskObjectInvoke (action);
+ }
+
+ public static TaskActionInvoker Create<TResult> (Action<Task<TResult>> action)
+ {
+ return new ActionTaskInvoke<TResult> (action);
+ }
+
+ public static TaskActionInvoker Create<TResult> (Action<Task<TResult>, object> action)
+ {
+ return new ActionTaskObjectInvoke<TResult> (action);
+ }
+
+ public static TaskActionInvoker Create<TResult> (Func<TResult> action)
+ {
+ return new FuncInvoke<TResult> (action);
+ }
+
+ public static TaskActionInvoker Create<TResult> (Func<object, TResult> action)
+ {
+ return new FuncObjectInvoke<TResult> (action);
+ }
+
+ public static TaskActionInvoker Create<TResult> (Func<Task, TResult> action)
+ {
+ return new FuncTaskInvoke<TResult> (action);
+ }
+
+ public static TaskActionInvoker Create<TResult> (Func<Task, object, TResult> action)
+ {
+ return new FuncTaskObjectInvoke<TResult> (action);
+ }
+
+ public static TaskActionInvoker Create<TResult, TNewResult> (Func<Task<TResult>, TNewResult> action)
+ {
+ return new FuncTaskInvoke<TResult, TNewResult> (action);
+ }
+
+ public static TaskActionInvoker Create<TResult, TNewResult> (Func<Task<TResult>, object, TNewResult> action)
+ {
+ return new FuncTaskObjectInvoke<TResult, TNewResult> (action);
+ }
+
+ public abstract Delegate Action { get; }
+ public abstract void Invoke (Task owner, object state, Task context);
+ }
+}
+#endif
Action<Task> continuationFunc = t => commonContinuation.SetResult (null);
foreach (Task t in ourTasks) {
- Task cont = new Task ((o) => continuationAction ((Task)o), t, cancellationToken, creationOptions, t);
+ Task cont = new Task (TaskActionInvoker.Create (continuationAction), null, cancellationToken, creationOptions, t);
t.ContinueWithCore (cont, continuationOptions, scheduler, trigger.TrySet);
cont.ContinueWith (continuationFunc);
}
TaskCompletionSource<TResult> source = new TaskCompletionSource<TResult> ();
foreach (Task t in ourTasks) {
- Task cont = new Task ((o) => source.SetResult (continuationFunction ((Task)o)), t, cancellationToken, creationOptions, t);
+ var cont = new Task (TaskActionInvoker.Create (continuationFunction), null, cancellationToken, creationOptions, t);
t.ContinueWithCore (cont, continuationOptions, scheduler, trigger.TrySet);
}
#if NET_4_0 || MOBILE
-using System;
-using System.Threading;
-
namespace System.Threading.Tasks
{
public class TaskFactory<TResult>
//
#if NET_4_0 || MOBILE
-using System;
+
using System.Runtime.CompilerServices;
namespace System.Threading.Tasks
public class Task<TResult> : Task
{
static readonly TaskFactory<TResult> factory = new TaskFactory<TResult> ();
- static readonly Action<object> emptyAction = delegate (object o) {};
TResult value;
- Func<object, TResult> function;
- Func<TResult> simpleFunction;
- object state;
[System.Diagnostics.DebuggerBrowsable (System.Diagnostics.DebuggerBrowsableState.Never)]
public TResult Result {
}
}
- public Task (Func<TResult> function) : this (function, TaskCreationOptions.None)
+ public Task (Func<TResult> function)
+ : this (function, TaskCreationOptions.None)
{
}
}
public Task (Func<TResult> function, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
- : base (emptyAction, null, cancellationToken, creationOptions)
+ : base (TaskActionInvoker.Create (function), null, cancellationToken, creationOptions, null)
{
if (function == null)
throw new ArgumentNullException ("function");
-
- this.simpleFunction = function;
- this.state = null;
}
- public Task (Func<object, TResult> function, object state) : this (function, state, TaskCreationOptions.None)
+ public Task (Func<object, TResult> function, object state)
+ : this (function, state, TaskCreationOptions.None)
{
}
}
public Task (Func<object, TResult> function, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
- : base (emptyAction, state, cancellationToken, creationOptions)
+ : base (TaskActionInvoker.Create (function), state, cancellationToken, creationOptions, null)
{
if (function == null)
throw new ArgumentNullException ("function");
-
- this.function = function;
- this.state = state;
}
- internal Task (Func<object, TResult> function,
- object state,
- CancellationToken cancellationToken,
- TaskCreationOptions creationOptions,
- Task parent)
- : base (emptyAction, state, cancellationToken, creationOptions, parent)
+ internal Task (TaskActionInvoker invoker, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions, Task parent)
+ : base (invoker, state, cancellationToken, creationOptions, parent)
{
- this.function = function;
- this.state = state;
}
-
- internal override void InnerInvoke ()
- {
- if (function != null)
- value = function (state);
- else if (simpleFunction != null)
- value = simpleFunction ();
-
- function = null;
- simpleFunction = null;
- state = null;
- }
-
+
public Task ContinueWith (Action<Task<TResult>> continuationAction)
{
return ContinueWith (continuationAction, TaskContinuationOptions.None);
if (scheduler == null)
throw new ArgumentNullException ("scheduler");
- Task t = new Task (l => continuationAction ((Task<TResult>)l),
- this,
+ Task t = new Task (TaskActionInvoker.Create (continuationAction),
+ null,
cancellationToken,
GetCreationOptions (continuationOptions),
this);
if (scheduler == null)
throw new ArgumentNullException ("scheduler");
- Task<TNewResult> t = new Task<TNewResult> ((o) => continuationFunction ((Task<TResult>)o),
- this,
+ var t = new Task<TNewResult> (TaskActionInvoker.Create (continuationFunction),
+ null,
cancellationToken,
GetCreationOptions (continuationOptions),
this);
if (scheduler == null)
throw new ArgumentNullException ("scheduler");
- var t = new Task (l => continuationAction (this, l),
+ var t = new Task (TaskActionInvoker.Create (continuationAction),
state,
cancellationToken,
GetCreationOptions (continuationOptions),
if (scheduler == null)
throw new ArgumentNullException ("scheduler");
- var t = new Task<TNewResult> (l => continuationFunction (this, l),
+ var t = new Task<TNewResult> (TaskActionInvoker.Create (continuationFunction),
state,
cancellationToken,
GetCreationOptions (continuationOptions),
}
}
+ [Test]
+ public void ContinueWith_StateValue ()
+ {
+ var t = Task.Factory.StartNew (l => {
+ Assert.AreEqual (1, l, "a-1");
+ }, 1);
+
+ var c = t.ContinueWith ((a, b) => {
+ Assert.AreEqual (t, a, "c-1");
+ Assert.AreEqual (2, b, "c-2");
+ }, 2);
+
+ var d = t.ContinueWith ((a, b) => {
+ Assert.AreEqual (t, a, "d-1");
+ Assert.AreEqual (3, b, "d-2");
+ return 77;
+ }, 3);
+
+ Assert.IsTrue (d.Wait (1000), "#1");
+
+ Assert.AreEqual (1, t.AsyncState, "#2");
+ Assert.AreEqual (2, c.AsyncState, "#3");
+ Assert.AreEqual (3, d.AsyncState, "#4");
+ }
+
+ [Test]
+ public void ContinueWith_StateValueGeneric ()
+ {
+ var t = Task<int>.Factory.StartNew (l => {
+ Assert.AreEqual (1, l, "a-1");
+ return 80;
+ }, 1);
+
+ var c = t.ContinueWith ((a, b) => {
+ Assert.AreEqual (t, a, "c-1");
+ Assert.AreEqual (2, b, "c-2");
+ return "c";
+ }, 2);
+
+ var d = t.ContinueWith ((a, b) => {
+ Assert.AreEqual (t, a, "d-1");
+ Assert.AreEqual (3, b, "d-2");
+ return 'd';
+ }, 3);
+
+ Assert.IsTrue (d.Wait (1000), "#1");
+
+ Assert.AreEqual (1, t.AsyncState, "#2");
+ Assert.AreEqual (80, t.Result, "#2r");
+ Assert.AreEqual (2, c.AsyncState, "#3");
+ Assert.AreEqual ("c", c.Result, "#3r");
+ Assert.AreEqual (3, d.AsyncState, "#4");
+ Assert.AreEqual ('d', d.Result, "#3r");
+ }
+
[Test]
public void FromResult ()
{
System.Threading.Tasks/IEventSlot.cs
System.Threading.Tasks/EventSlots.cs
System.Threading.Tasks/CompletionSlot.cs
+System.Threading.Tasks/TaskActionInvoker.cs
System.Threading.Tasks/TaskDebuggerView.cs
System.Threading.Tasks/TaskCompletionSource.cs
System.Threading.Tasks/TaskSchedulerException.cs