How can I pass a state object to a continuation task?

taskcontinuationoptions
c# combine two tasks
task continuewith example
c# task exception handling continuewith
task after complete c#
task continuewith not called
task delay continuewith
c# chaining async methods

I'm using the .NET 4.0 Task Parallel Library with C# (my first time using TPL)

I have a task A which I want to run to completion before firing off a bunch of other tasks (B,C,D, etc). I therefore want to create tasks B,C,D etc as continuations of task A. However, I want to pass a 'state' object to task B, another state object to task C, etc.

I can pass a state object to task A by simply using a Task constructor overload that takes a state object, for example http://msdn.microsoft.com/en-us/library/dd783035.aspx describes this Task constructor overload:

Task(Action<Object>, Object, CancellationToken) 

This works fine, and the second argument is my 'state' object.

I want to create a continuation task, e.g. for task B:

Task taskB = taskA.ContinueWith(/* args here*/)

However, I cannot see a ContinueWith() overload (see http://msdn.microsoft.com/en-us/library/dd235663.aspx) which allows me to pass a 'state' object to a continuation task. How can this be done?

Notes:

  1. I do not have the 'state' object for taskB available at the time I create taskA
  2. The 'state' object for taskB is not an output (return value) of taskA

For some context, what I am doing is creating taskB, taskC, etc. inside a couple of loops and so I am passing the value of the loop variables to taskB, taskC, etc. using a state object, in order to avoid the problem of always ending up with the final value of the loop variables in the tasks (the closure issue).

The simplest approach would probably be to simply capture it in the Func<Task, TResult> you pass into ContinueWith. For example:

object taskBState = GetStateHere();
Task taskB = taskA.ContinueWith(task => RealContinuation(task, taskBState));

Personally I find it easier to capture state like that than getting the state passed in anyway.

Chaining Tasks by Using Continuation Tasks, Example 837 demonstrates how you might use a state object to pass an integer ContinueWith(OnCompletion,asyncState); } void OnCompletion(Task<int> task​  You can later access this state object by using the Task.AsyncState property. This state object is null if you do not provide a value. Continuation state is useful when you convert existing code that uses the Asynchronous Programming Model (APM) to use the TPL. In the APM, you typically provide object state in the BeginMethod method and later access that state by using the IAsyncResult.AsyncState property.

You can't. They expect you to use the power of closures. Just define an additional variable inside the loops to capture the current value for that closure. See this answer from Jon Skeet for more details on capturing and closures.

Update: Or Jon Skeet could beat me to reply directly to your question saying exactly the same thing. :)

Task.ContinueWith Method (System.Threading.Tasks), A continuation is a delegate that you can attach to a task and tell the task “run this an object parameter just pass that value through to the continuation the continuation if the antecedent task completes in a matching state. And every single continuation task could actually have a state. So we'll start with a very simple function, more like a public static function that returns anything, it could return anything

For future readers, ContinueWith() function, at least in .NET 4.7, has an overload that allows you to pass state parameter:

public System.Threading.Tasks.Task ContinueWith(
  Action<System.Threading.Tasks.Task,object> continuationAction, object state,
  System.Threading.CancellationToken cancellationToken, 
  System.Threading.Tasks.TaskContinuationOptions continuationOptions, 
  System.Threading.Tasks.TaskScheduler scheduler);

See this MSDN article for more details.

C# 6.0 Cookbook: Solutions for C# Developers, Once reified as an explicit continuation, the state of a computation can be saved at the The caller of the paused method then receives a task representing write asynchronous methods, without having to resort to continuation-passing-​style  There are a few more “scheduling options” that are not passed to the TaskScheduler.The HideScheduler option (introduced in .NET 4.5) will use the given task scheulder to schedule the continuation, but then will pretend that there is no current task scheduler while the continuation is executing; this can be used as a workaround for the unexpected default task scheduler (described below).

Programming WCF Services: Design and Build Maintainable , Luckily, in our code, we ended up calling Result on the Task object, which since there's no way to pass a 'state' object into ContinueWith in . - [Instructor] Now that we've looked into cancellations,…if you remember, in the previous course,…not the pervious module, you actually had…done something called task continuations,…where we had an antecedent…and then we were able to get the result…from the antecedent in the continuation task.…Now this is continuation,…except this time we are going…to pass state with

A Tour of Task, Part 7: Continuations, working with task in C# and the proper way to pass a parameter to a task. public static void MyTask() { for (int i = 0; i < 10; i++) { object arg = i; var task = new TaskFactory(). C# Task Continuation, Exceptions and Result. Creates a continuation that receives caller-supplied state information and a cancellation token and that executes asynchronously when the target Task completes. ContinueWith (Action<Task,Object>, Object) Creates a continuation that receives caller-supplied state information and executes when the target Task completes.

ECOOP 2012 -- Object-Oriented Programming: 26th European , I ran into a problem similar to this: Memory leak in recursive continuation Tasks I have a state object (e.g. of type Tuple<,,,>) and I pass this to  And the same local variable I am passing as parameter to the task. Hence preventing my tasks to share states. Conclusion: In this article we have seen how it can be sometime quite erroneous to pass or use the variable which share states. And how we can save ourselves from this behavior by passing the parameter to the task in C#. References:

Comments
  • Thanks for the quick reply. I tried what you suggest in a test program and it worked fine. I know I need to improve my understanding of closures... and yes, this does feel like an easier way of capturing state...
  • Unfortunately MS changed their mind about this (link), after realizing some of the performance impact vs. state parameters in long continuation chains with closures. You can write code that works in both 4.0 and 4.5, but wont take advantage of significant performance improvement in 4.5; or write 4.5-specific code with an explicit parameter and no closure.