Create continuations using the Task Parallel Library that can run immediately after the execution of the antecedent is complete or to chain tasks as continuations A continuation is like a delegate that can be attached to a task so that you can execute it once the task has finished its execution. When working with asynchronous programming in .Net, you might often need to chain tasks as continuations or pass data to a task based on the data returned by another task. To achieve this, you would need to leverage continuations. Continuations in the Task Parallel Library Before TPL was around, continuations were performed using callback methods. A continuation is just another task and doesn’t block the thread on which it is called. While continuation in TPL is simple to implement, here’s a quick look at the benefits that task continuations have to offer: Invoke one or more continuations using the same antecedent Invoke a continuation when one or more antecedents have completed their execution Specify certain conditions based on which the continuations should be executed Chain continuations and pass data from an antecedent task to a continuation task Note that the ContinueWith method returns a task instance allowing you to have a chain of ContinueWith calls. Also, unlike the await keyword, the ContinueWith method doesn’t preserve the state and is executed by the default thread scheduler (if you don’t provide one) although you can also specify your custom scheduler when invoking the ContinueWith method. Creating continuation tasks using ContinueWith method You can create continuation tasks in TPL using the ContinueWith method on a Task. It should be noted that this method accepts just one parameter — the task that needs to be executed when the antecedent has completed its execution. The task instance on which the ContinueWith method is invoked is known as the antecedent task. Instead, the task that is executed by the ContinueWith method after execution of its antecedent task is complete is known as the continuation task. Let’s look at an example. Here’s how the syntax of the ContinueWith method looks: public Task<TResult> ContinueWith<TResult>( Func<Task, TResult> continuationFunction ) The ContinueWith method in turn returns another continuation task. Here’s a code snippet that illustrates how you can create a continuation task using one antecedent: public static void Main() { Task<string> initialTask = Task.Run(() => DateTime.Today.ToShortDateString()); Task continuation = initialTask.ContinueWith(antecedentTask => Console.WriteLine("Today is {0}.", antecedentTask.Result)); Console.Read(); } Refer to the code snippet given above. The first task is executed using a call to the Task.Run method. This is the antecedent task in our example. Once the execution of the antecedent task is complete, the continuation task is executed in the next statement. Note that you can also create a continuation that is to be executed when one or more antecedents have completed their execution. To execute a continuation when all the antecedent tasks are complete, you can take advantage of the Task.WhenAll or the TaskFactory.ContinueWhenAll methods. Alternatively, you can execute a continuation when any of the antecedent tasks are complete using the Task.WhenAny or TaskFactory.ContinueWhenAny methods. It should be noted that none of these methods block the calling thread. Although there are several methods (ie., Wait, WaitAll, WaitAny, Result, and GetAwaiter().GetResult()) that allow you to wait till the execution of a task is complete, all of these synchronously block the calling thread. You can also specify continuation options when using the ContinueWith, ContinueWhenAll methods. To do this, you would need to take advantage of the Task.TaskContinuationOptions enumeration of the System.Threading namespace. As an example, you can ensure that a continuation executes only after the execution of the antecedent has completed its execution. var continuationTask = task.ContinueWith( (antecedentTask) => { Console.WriteLine("This will execute only after the antecedent has completed its execution."); } , TaskContinuationOptions.OnlyOnRanToCompletion); Here’s another example that illustrates how task continuation options can be used to execute a continuation only after the antecedent has completed its execution. public static void Main() { var task = Task.Run(() => { return "Joydip"; }); var t = task.ContinueWith((antecedent) => { Console.WriteLine("Hello {0}", antecedent.Result); }, TaskContinuationOptions.OnlyOnRanToCompletion); Console.Read(); } If you use ContinueWith without mentioning any special flag, the continuation will always be executed regardless of the state of the antecedent, i.e., the continuation will be executed even if the antecedent has completed its executed in a faulted or a cancelled state. As a side note, let me tell you that it is advisable to avoid using ContinueWith in your applications. In doing so, you can avoid threading issues and also avoid allocating an extra task instance when it is not needed in your application. You can do away from ContinueWith by using task helpers. I will discuss more on this in a later post here. Related content feature What is Rust? Safe, fast, and easy software development Unlike most programming languages, Rust doesn't make you choose between speed, safety, and ease of use. Find out how Rust delivers better code with fewer compromises, and a few downsides to consider before learning Rust. By Serdar Yegulalp Nov 20, 2024 11 mins Rust Programming Languages Software Development how-to Kotlin for Java developers: Classes and coroutines Kotlin was designed to bring more flexibility and flow to programming in the JVM. Here's an in-depth look at how Kotlin makes working with classes and objects easier and introduces coroutines to modernize concurrency. By Matthew Tyson Nov 20, 2024 9 mins Java Kotlin Programming Languages analysis Azure AI Foundry tools for changes in AI applications Microsoft’s launch of Azure AI Foundry at Ignite 2024 signals a welcome shift from chatbots to agents and to using AI for business process automation. By Simon Bisson Nov 20, 2024 7 mins Microsoft Azure Generative AI Development Tools news Microsoft unveils imaging APIs for Windows Copilot Runtime Generative AI-backed APIs will allow developers to build image super resolution, image segmentation, object erase, and OCR capabilities into Windows applications. By Paul Krill Nov 19, 2024 2 mins Generative AI APIs Development Libraries and Frameworks Resources Videos