ContinueWith(Action<Task,Object>, Object, CancellationToken, TaskContinuationOptions, TaskScheduler)

建立一個延續,接收呼叫者提供的狀態資訊及取消標記,並在目標 Task 完成時執行。 接續會根據一組指定的條件執行,並使用指定的排程器。

ContinueWith<TResult>(Func<Task,Object,TResult>, Object, CancellationToken, TaskContinuationOptions, TaskScheduler)

建立一個延續,當目標 Task 完成並回傳值時,根據指定的任務延續選項執行。 接續會接收呼叫端提供的狀態資訊和取消令牌,並使用指定的排程器。

ContinueWith<TResult>(Func<Task,TResult>, CancellationToken, TaskContinuationOptions, TaskScheduler)

建立根據指定接續選項執行的接續,並傳回值。 接續會傳遞取消令牌,並使用指定的排程器。

public:
 System::Threading::Tasks::Task ^ ContinueWith(Action<System::Threading::Tasks::Task ^, System::Object ^> ^ continuationAction, System::Object ^ state, System::Threading::CancellationToken cancellationToken, System::Threading::Tasks::TaskContinuationOptions continuationOptions, System::Threading::Tasks::TaskScheduler ^ scheduler);
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);
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);
member this.ContinueWith : Action<System.Threading.Tasks.Task, obj> * obj * System.Threading.CancellationToken * System.Threading.Tasks.TaskContinuationOptions * System.Threading.Tasks.TaskScheduler -> System.Threading.Tasks.Task
Public Function ContinueWith (continuationAction As Action(Of Task, Object), state As Object, cancellationToken As CancellationToken, continuationOptions As TaskContinuationOptions, scheduler As TaskScheduler) As Task
public:
 System::Threading::Tasks::Task ^ ContinueWith(Action<System::Threading::Tasks::Task ^> ^ continuationAction, System::Threading::CancellationToken cancellationToken, System::Threading::Tasks::TaskContinuationOptions continuationOptions, System::Threading::Tasks::TaskScheduler ^ scheduler);
public System.Threading.Tasks.Task ContinueWith(Action<System.Threading.Tasks.Task> continuationAction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler);
member this.ContinueWith : Action<System.Threading.Tasks.Task> * System.Threading.CancellationToken * System.Threading.Tasks.TaskContinuationOptions * System.Threading.Tasks.TaskScheduler -> System.Threading.Tasks.Task
Public Function ContinueWith (continuationAction As Action(Of Task), cancellationToken As CancellationToken, continuationOptions As TaskContinuationOptions, scheduler As TaskScheduler) As Task

以下是一個使用 ContinueWith 在背景與使用者介面執行緒中同時執行工作的範例。

private void Button1_Click(object sender, EventArgs e)
   var backgroundScheduler = TaskScheduler.Default;
   var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
   Task.Factory.StartNew(delegate { DoBackgroundComputation(); },
                         backgroundScheduler).
   ContinueWith(delegate { UpdateUI(); }, uiScheduler).
                ContinueWith(delegate { DoAnotherBackgroundComputation(); },
                             backgroundScheduler).
                ContinueWith(delegate { UpdateUIAgain(); }, uiScheduler);
Private Sub Button1_Click(ByVal sender As System.Object,
                          ByVal e As System.EventArgs) Handles Button1.Click
   Dim backgroundScheduler = TaskScheduler.Default
   Dim uiScheduler = TaskScheduler.FromCurrentSynchronizationContext()
   Task.Factory.StartNew(Sub()
                           DoBackgroundComputation()
                         End Sub, backgroundScheduler).ContinueWith(Sub(t)
                            UpdateUI()
                         End Sub, uiScheduler).ContinueWith(Sub(t)
                            DoAnotherBackgroundComputation()
                         End Sub, backgroundScheduler).ContinueWith(Sub(t)
                            UpdateUIAgain()
                         End Sub, uiScheduler)
End Sub
    	

退回 Task 的任務在當前任務完成前不會排程執行。 若未符合參數所指定的 continuationOptions 條件,續接任務將被取消而非排程。

public:
 System::Threading::Tasks::Task ^ ContinueWith(Action<System::Threading::Tasks::Task ^, System::Object ^> ^ continuationAction, System::Object ^ state, System::Threading::Tasks::TaskScheduler ^ scheduler);
public System.Threading.Tasks.Task ContinueWith(Action<System.Threading.Tasks.Task,object> continuationAction, object state, System.Threading.Tasks.TaskScheduler scheduler);
public System.Threading.Tasks.Task ContinueWith(Action<System.Threading.Tasks.Task,object?> continuationAction, object? state, System.Threading.Tasks.TaskScheduler scheduler);
member this.ContinueWith : Action<System.Threading.Tasks.Task, obj> * obj * System.Threading.Tasks.TaskScheduler -> System.Threading.Tasks.Task
Public Function ContinueWith (continuationAction As Action(Of Task, Object), state As Object, scheduler As TaskScheduler) As Task
public:
 System::Threading::Tasks::Task ^ ContinueWith(Action<System::Threading::Tasks::Task ^, System::Object ^> ^ continuationAction, System::Object ^ state, System::Threading::Tasks::TaskContinuationOptions continuationOptions);
public System.Threading.Tasks.Task ContinueWith(Action<System.Threading.Tasks.Task,object> continuationAction, object state, System.Threading.Tasks.TaskContinuationOptions continuationOptions);
public System.Threading.Tasks.Task ContinueWith(Action<System.Threading.Tasks.Task,object?> continuationAction, object? state, System.Threading.Tasks.TaskContinuationOptions continuationOptions);
member this.ContinueWith : Action<System.Threading.Tasks.Task, obj> * obj * System.Threading.Tasks.TaskContinuationOptions -> System.Threading.Tasks.Task
Public Function ContinueWith (continuationAction As Action(Of Task, Object), state As Object, continuationOptions As TaskContinuationOptions) As Task
public:
 System::Threading::Tasks::Task ^ ContinueWith(Action<System::Threading::Tasks::Task ^, System::Object ^> ^ continuationAction, System::Object ^ state, System::Threading::CancellationToken cancellationToken);
public System.Threading.Tasks.Task ContinueWith(Action<System.Threading.Tasks.Task,object> continuationAction, object state, System.Threading.CancellationToken cancellationToken);
public System.Threading.Tasks.Task ContinueWith(Action<System.Threading.Tasks.Task,object?> continuationAction, object? state, System.Threading.CancellationToken cancellationToken);
member this.ContinueWith : Action<System.Threading.Tasks.Task, obj> * obj * System.Threading.CancellationToken -> System.Threading.Tasks.Task
Public Function ContinueWith (continuationAction As Action(Of Task, Object), state As Object, cancellationToken As CancellationToken) As Task
public:
 System::Threading::Tasks::Task ^ ContinueWith(Action<System::Threading::Tasks::Task ^> ^ continuationAction);
public System.Threading.Tasks.Task ContinueWith(Action<System.Threading.Tasks.Task> continuationAction);
member this.ContinueWith : Action<System.Threading.Tasks.Task> -> System.Threading.Tasks.Task
Public Function ContinueWith (continuationAction As Action(Of Task)) As Task

以下範例定義了一個任務,該任務會填充一個陣列,包含 100 個隨機日期和時間值。 它會用這個 ContinueWith(Action<Task>) 方法在陣列完全填滿後,選擇最早和最新的日期值。

using System;
using System.Threading.Tasks;
public class Example
   public static void Main()
      var firstTask = Task.Factory.StartNew( () => {
                               Random rnd = new Random();
                               DateTime[] dates = new DateTime[100];
                               Byte[] buffer = new Byte[8];
                               int ctr = dates.GetLowerBound(0);
                               while (ctr <= dates.GetUpperBound(0)) {
                                  rnd.NextBytes(buffer);
                                  long ticks = BitConverter.ToInt64(buffer, 0);
                                  if (ticks <= DateTime.MinValue.Ticks | ticks >= DateTime.MaxValue.Ticks)
                                     continue;
                                  dates[ctr] = new DateTime(ticks);
                                  ctr++;
                               return dates;
      Task continuationTask = firstTask.ContinueWith( (antecedent) => {
                             DateTime[] dates = antecedent.Result;
                             DateTime earliest = dates[0];
                             DateTime latest = earliest;
                             for (int ctr = dates.GetLowerBound(0) + 1; ctr <= dates.GetUpperBound(0); ctr++) {
                                if (dates[ctr] < earliest) earliest = dates[ctr];
                                if (dates[ctr] > latest) latest = dates[ctr];
                             Console.WriteLine("Earliest date: {0}", earliest);
                             Console.WriteLine("Latest date: {0}", latest);
      // Since a console application otherwise terminates, wait for the continuation to complete.
     continuationTask.Wait();
// The example displays output like the following:
//       Earliest date: 2/11/0110 12:03:41 PM
//       Latest date: 7/29/9989 2:14:49 PM
open System
open System.Threading.Tasks
let firstTask =
    Task.Factory.StartNew(fun () ->
        let rnd = Random()
        let dates = Array.zeroCreate 100
        let buffer = Array.zeroCreate 8
        let mutable i = dates.GetLowerBound 0
        while i <= dates.GetUpperBound 0 do
            rnd.NextBytes buffer
            let ticks = BitConverter.ToInt64(buffer, 0)
            if ticks > DateTime.MinValue.Ticks && ticks < DateTime.MaxValue.Ticks then
                dates[i] <- DateTime ticks
                i <- i + 1
        dates)
let continuationTask =
    firstTask.ContinueWith(
        Action<Task<DateTime[]>>(fun antecedent ->
            let dates: DateTime[] = antecedent.Result
            let mutable earliest = dates[0]
            let mutable latest = earliest
            for i = dates.GetLowerBound 0 + 1 to dates.GetUpperBound 0 do
                if dates.[i] < earliest then
                    earliest <- dates.[i]
                if dates.[i] > latest then
                    latest <- dates.[i]
            printfn $"Earliest date: {earliest}"
            printfn $"Latest date: {latest}")
// Since a console application otherwise terminates, wait for the continuation to complete.
continuationTask.Wait()
// The example displays output like the following:
//       Earliest date: 2/11/0110 12:03:41 PM
//       Latest date: 7/29/9989 2:14:49 PM
Imports System.Threading.Tasks
Module Example
   Public Sub Main()
      Dim firstTask = Task.Factory.StartNew( Function()
                               Dim rnd As New Random()
                               Dim dates(99) As Date
                               Dim buffer(7) As Byte
                               Dim ctr As Integer = dates.GetLowerBound(0)
                               Do While ctr <= dates.GetUpperBound(0)
                                  rnd.NextBytes(buffer)
                                  Dim ticks As Long = BitConverter.ToInt64(buffer, 0)
                                  If ticks <= DateTime.MinValue.Ticks Or ticks >= DateTime.MaxValue.Ticks Then Continue Do
                                  dates(ctr) = New Date(ticks)
                                  ctr += 1
                               Return dates
                            End Function )
      Dim continuationTask As Task = firstTask.ContinueWith( Sub(antecedent)
                             Dim dates() As Date = antecedent.Result
                             Dim earliest As Date = dates(0)
                             Dim latest As Date = earliest
                             For ctr As Integer = dates.GetLowerBound(0) + 1 To dates.GetUpperBound(0)
                                If dates(ctr) < earliest Then earliest = dates(ctr)
                                If dates(ctr) > latest Then latest = dates(ctr)
                             Console.WriteLine("Earliest date: {0}", earliest)
                             Console.WriteLine("Latest date: {0}", latest)
                          End Sub)                      
      ' Since a console application otherwise terminates, wait for the continuation to complete.
      continuationTask.Wait()
   End Sub
End Module
' The example displays output like the following:
'       Earliest date: 2/11/0110 12:03:41 PM
'       Latest date: 7/29/9989 2:14:49 PM

由於主控台應用程式可能在延續任務執行前終止,因此呼叫此 Wait() 方法以確保延續任務在範例結束前完成執行。

更多範例請參見「 使用延續任務串接任務」。

回傳 Task 的任務不會排程執行,直到目前任務完成,無論是因成功完成、因未處理異常而錯誤,或因被取消而提前退出。

public:
 System::Threading::Tasks::Task ^ ContinueWith(Action<System::Threading::Tasks::Task ^> ^ continuationAction, System::Threading::Tasks::TaskContinuationOptions continuationOptions);
public System.Threading.Tasks.Task ContinueWith(Action<System.Threading.Tasks.Task> continuationAction, System.Threading.Tasks.TaskContinuationOptions continuationOptions);
member this.ContinueWith : Action<System.Threading.Tasks.Task> * System.Threading.Tasks.TaskContinuationOptions -> System.Threading.Tasks.Task
Public Function ContinueWith (continuationAction As Action(Of Task), continuationOptions As TaskContinuationOptions) As Task

以下範例示範如何指定 TaskContinuationOptions 續接任務在前件任務完成時應同步執行。 (如果指定的任務在呼叫時已完成 ContinueWith ,同步延續會在呼叫 ContinueWith執行緒上執行。)

public class TaskCounter
   private volatile int _count;
   public void Track(Task t)
      if (t == null) throw new ArgumentNullException("t");
      Interlocked.Increment(ref _count);
      t.ContinueWith(ct => Interlocked.Decrement(ref _count), TaskContinuationOptions.ExecuteSynchronously);
   public int NumberOfActiveTasks { get { return _count; } }
Public Class TaskCounter
   Private _count as Integer
   Public Sub Track(ByVal t as Task)
      If t is Nothing Then Throw New ArgumentNullException("t")
      Interlocked.Increment(_count)
      t.ContinueWith(Sub(ct)
                        Interlocked.Decrement(_count)
                     End Sub,
                     TaskContinuationOptions.ExecuteSynchronously)
   End Sub
   Public ReadOnly Property NumberOfActiveTasks As Integer
         Return _count
      End Get
   End Property
End Class
    	

退回 Task 的任務在當前任務完成前不會排程執行。 若未符合參數中指定的 continuationOptions 續航標準,續航任務將被取消而非排程。

public:
 System::Threading::Tasks::Task ^ ContinueWith(Action<System::Threading::Tasks::Task ^> ^ continuationAction, System::Threading::CancellationToken cancellationToken);
public System.Threading.Tasks.Task ContinueWith(Action<System.Threading.Tasks.Task> continuationAction, System.Threading.CancellationToken cancellationToken);
member this.ContinueWith : Action<System.Threading.Tasks.Task> * System.Threading.CancellationToken -> System.Threading.Tasks.Task
Public Function ContinueWith (continuationAction As Action(Of Task), cancellationToken As CancellationToken) As Task
public:
 System::Threading::Tasks::Task ^ ContinueWith(Action<System::Threading::Tasks::Task ^, System::Object ^> ^ continuationAction, System::Object ^ state);
public System.Threading.Tasks.Task ContinueWith(Action<System.Threading.Tasks.Task,object> continuationAction, object state);
public System.Threading.Tasks.Task ContinueWith(Action<System.Threading.Tasks.Task,object?> continuationAction, object? state);
member this.ContinueWith : Action<System.Threading.Tasks.Task, obj> * obj -> System.Threading.Tasks.Task
Public Function ContinueWith (continuationAction As Action(Of Task, Object), state As Object) As Task
public:
 System::Threading::Tasks::Task ^ ContinueWith(Action<System::Threading::Tasks::Task ^> ^ continuationAction, System::Threading::Tasks::TaskScheduler ^ scheduler);
public System.Threading.Tasks.Task ContinueWith(Action<System.Threading.Tasks.Task> continuationAction, System.Threading.Tasks.TaskScheduler scheduler);
member this.ContinueWith : Action<System.Threading.Tasks.Task> * System.Threading.Tasks.TaskScheduler -> System.Threading.Tasks.Task
Public Function ContinueWith (continuationAction As Action(Of Task), scheduler As TaskScheduler) As Task
public:
generic <typename TResult>
 System::Threading::Tasks::Task<TResult> ^ ContinueWith(Func<System::Threading::Tasks::Task ^, System::Object ^, TResult> ^ continuationFunction, System::Object ^ state, System::Threading::Tasks::TaskScheduler ^ scheduler);
public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(Func<System.Threading.Tasks.Task,object,TResult> continuationFunction, object state, System.Threading.Tasks.TaskScheduler scheduler);
public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(Func<System.Threading.Tasks.Task,object?,TResult> continuationFunction, object? state, System.Threading.Tasks.TaskScheduler scheduler);
member this.ContinueWith : Func<System.Threading.Tasks.Task, obj, 'Result> * obj * System.Threading.Tasks.TaskScheduler -> System.Threading.Tasks.Task<'Result>
Public Function ContinueWith(Of TResult) (continuationFunction As Func(Of Task, Object, TResult), state As Object, scheduler As TaskScheduler) As Task(Of TResult)
TResult
public:
generic <typename TResult>
 System::Threading::Tasks::Task<TResult> ^ ContinueWith(Func<System::Threading::Tasks::Task ^, System::Object ^, TResult> ^ continuationFunction, System::Object ^ state, System::Threading::CancellationToken cancellationToken, System::Threading::Tasks::TaskContinuationOptions continuationOptions, System::Threading::Tasks::TaskScheduler ^ scheduler);
public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(Func<System.Threading.Tasks.Task,object,TResult> continuationFunction, object state, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler);
public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(Func<System.Threading.Tasks.Task,object?,TResult> continuationFunction, object? state, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler);
member this.ContinueWith : Func<System.Threading.Tasks.Task, obj, 'Result> * obj * System.Threading.CancellationToken * System.Threading.Tasks.TaskContinuationOptions * System.Threading.Tasks.TaskScheduler -> System.Threading.Tasks.Task<'Result>
Public Function ContinueWith(Of TResult) (continuationFunction As Func(Of Task, Object, TResult), state As Object, cancellationToken As CancellationToken, continuationOptions As TaskContinuationOptions, scheduler As TaskScheduler) As Task(Of TResult)
TResult
public:
generic <typename TResult>
 System::Threading::Tasks::Task<TResult> ^ ContinueWith(Func<System::Threading::Tasks::Task ^, TResult> ^ continuationFunction, System::Threading::CancellationToken cancellationToken, System::Threading::Tasks::TaskContinuationOptions continuationOptions, System::Threading::Tasks::TaskScheduler ^ scheduler);
public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(Func<System.Threading.Tasks.Task,TResult> continuationFunction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler);
member this.ContinueWith : Func<System.Threading.Tasks.Task, 'Result> * System.Threading.CancellationToken * System.Threading.Tasks.TaskContinuationOptions * System.Threading.Tasks.TaskScheduler -> System.Threading.Tasks.Task<'Result>
Public Function ContinueWith(Of TResult) (continuationFunction As Func(Of Task, TResult), cancellationToken As CancellationToken, continuationOptions As TaskContinuationOptions, scheduler As TaskScheduler) As Task(Of TResult)
TResult // Task.Wait() // Expected results: // This sample demonstrates branched continuation sequences - Task+Commit or Task+Rollback. // Notice that no if statements are used. // The first sequence is successful - tran1 and commitTran1 are executed. rollbackTran1 is canceled. // The second sequence is unsuccessful - tran2 and rollbackTran2 are executed. tran2 is faulted, and commitTran2 is canceled. // Documentation: // http://msdn.microsoft.com/library/system.threading.tasks.taskcontinuationoptions(VS.100).aspx static void Main() Action success = () => Console.WriteLine("Task={0}, Thread={1}: Begin successful transaction", Task.CurrentId, Thread.CurrentThread.ManagedThreadId); Action failure = () => Console.WriteLine("Task={0}, Thread={1}: Begin transaction and encounter an error", Task.CurrentId, Thread.CurrentThread.ManagedThreadId); throw new InvalidOperationException("SIMULATED EXCEPTION"); Action<Task> commit = (antecendent) => Console.WriteLine("Task={0}, Thread={1}: Commit transaction", Task.CurrentId, Thread.CurrentThread.ManagedThreadId); Action<Task> rollback = (antecendent) => // "Observe" your antecedent's exception so as to avoid an exception // being thrown on the finalizer thread var unused = antecendent.Exception; Console.WriteLine("Task={0}, Thread={1}: Rollback transaction", Task.CurrentId, Thread.CurrentThread.ManagedThreadId); // Successful transaction - Begin + Commit Console.WriteLine("Demonstrating a successful transaction"); // Initial task // Treated as "fire-and-forget" -- any exceptions will be cleaned up in rollback continuation Task tran1 = Task.Factory.StartNew(success); // The following task gets scheduled only if tran1 completes successfully var commitTran1 = tran1.ContinueWith(commit, TaskContinuationOptions.OnlyOnRanToCompletion); // The following task gets scheduled only if tran1 DOES NOT complete successfully var rollbackTran1 = tran1.ContinueWith(rollback, TaskContinuationOptions.NotOnRanToCompletion); // For demo purposes, wait for the sample to complete commitTran1.Wait(); // ----------------------------------------------------------------------------------- // Failed transaction - Begin + exception + Rollback Console.WriteLine("\nDemonstrating a failed transaction"); // Initial task // Treated as "fire-and-forget" -- any exceptions will be cleaned up in rollback continuation Task tran2 = Task.Factory.StartNew(failure); // The following task gets scheduled only if tran2 completes successfully var commitTran2 = tran2.ContinueWith(commit, TaskContinuationOptions.OnlyOnRanToCompletion); // The following task gets scheduled only if tran2 DOES NOT complete successfully var rollbackTran2 = tran2.ContinueWith(rollback, TaskContinuationOptions.NotOnRanToCompletion); // For demo purposes, wait for the sample to complete rollbackTran2.Wait();
open System
open System.Threading
open System.Threading.Tasks
// Demonstrated features:
//      TaskContinuationOptions
//		Task.ContinueWith()
// 		Task.Factory
//		Task.Wait()
// Expected results:
// 		This sample demonstrates branched continuation sequences - Task+Commit or Task+Rollback.
//      Notice that no if statements are used.
//		The first sequence is successful - tran1 and commitTran1 are executed. rollbackTran1 is canceled.
//		The second sequence is unsuccessful - tran2 and rollbackTran2 are executed. tran2 is faulted, and commitTran2 is canceled.
// Documentation:
//		http://msdn.microsoft.com/library/system.threading.tasks.taskcontinuationoptions(VS.100).aspx
let success =
    fun () ->
        printfn $"Task={Task.CurrentId}, Thread={Thread.CurrentThread.ManagedThreadId}: Begin successful transaction"
let failure =
    fun () ->
        printfn
            $"Task={Task.CurrentId}, Thread={Thread.CurrentThread.ManagedThreadId}: Begin transaction and encounter an error"
        raise (InvalidOperationException "SIMULATED EXCEPTION")
let commit =
    fun antecendent ->
        printfn $"Task={Task.CurrentId}, Thread={Thread.CurrentThread.ManagedThreadId}: Commit transaction"
let rollback =
    fun (antecendent: Task) ->
        // "Observe" your antecedent's exception so as to avoid an exception
        // being thrown on the finalizer thread
        let unused = antecendent.Exception
        printfn $"Task={Task.CurrentId}, Thread={Thread.CurrentThread.ManagedThreadId}: Rollback transaction"
// Successful transaction - Begin + Commit
printfn "Demonstrating a successful transaction"
// Initial task
// Treated as "fire-and-forget" -- any exceptions will be cleaned up in rollback continuation
let tran1 = Task.Factory.StartNew success
// The following task gets scheduled only if tran1 completes successfully
let commitTran1 =
    tran1.ContinueWith(commit, TaskContinuationOptions.OnlyOnRanToCompletion)
// The following task gets scheduled only if tran1 DOES NOT complete successfully
let rollbackTran1 =
    tran1.ContinueWith(rollback, TaskContinuationOptions.NotOnRanToCompletion)
// For demo purposes, wait for the sample to complete
commitTran1.Wait()
// -----------------------------------------------------------------------------------
// Failed transaction - Begin + exception + Rollback
printfn "\nDemonstrating a failed transaction"
// Initial task
// Treated as "fire-and-forget" -- any exceptions will be cleaned up in rollback continuation
let tran2: Task = Task.Factory.StartNew failure
// The following task gets scheduled only if tran2 completes successfully
let commitTran2 =
    tran2.ContinueWith(Action<Task> commit, TaskContinuationOptions.OnlyOnRanToCompletion)
// The following task gets scheduled only if tran2 DOES NOT complete successfully
let rollbackTran2 =
    tran2.ContinueWith(Action<Task> rollback, TaskContinuationOptions.NotOnRanToCompletion)
// For demo purposes, wait for the sample to complete
rollbackTran2.Wait()
Imports System.Threading
Imports System.Threading.Tasks
Module ContuationOptionsDemo
    ' Demonstrated features:
    '   TaskContinuationOptions
    '   Task.ContinueWith()
    '   Task.Factory
    '   Task.Wait()
    ' Expected results:
    '   This sample demonstrates branched continuation sequences - Task+Commit or Task+Rollback.
    '   Notice that no if statements are used.
    '   The first sequence is successful - tran1 and commitTran1 are executed. rollbackTran1 is canceled.
    '   The second sequence is unsuccessful - tran2 and rollbackTran2 are executed. tran2 is faulted, and commitTran2 is canceled.
    ' Documentation:
    '   http://msdn.microsoft.com/library/system.threading.tasks.taskcontinuationoptions(VS.100).aspx
    Private Sub Main()
        Dim success As Action = Sub()
                                    Console.WriteLine("Task={0}, Thread={1}: Begin successful transaction", Task.CurrentId, Thread.CurrentThread.ManagedThreadId)
                                End Sub
        Dim failure As Action = Sub()
                                    Console.WriteLine("Task={0}, Thread={1}: Begin transaction and encounter an error", Task.CurrentId, Thread.CurrentThread.ManagedThreadId)
                                    Throw New InvalidOperationException("SIMULATED EXCEPTION")
                                End Sub
        Dim commit As Action(Of Task) = Sub(antecendent)
                                            Console.WriteLine("Task={0}, Thread={1}: Commit transaction", Task.CurrentId, Thread.CurrentThread.ManagedThreadId)
                                        End Sub
        Dim rollback As Action(Of Task) = Sub(antecendent)
                                              ' "Observe" your antecedent's exception so as to avoid an exception
                                              ' being thrown on the finalizer thread
                                              Dim unused = antecendent.Exception
                                              Console.WriteLine("Task={0}, Thread={1}: Rollback transaction", Task.CurrentId, Thread.CurrentThread.ManagedThreadId)
                                          End Sub
        ' Successful transaction - Begin + Commit
        Console.WriteLine("Demonstrating a successful transaction")
        ' Initial task
        ' Treated as "fire-and-forget" -- any exceptions will be cleaned up in rollback continuation
        Dim tran1 As Task = Task.Factory.StartNew(success)
        ' The following task gets scheduled only if tran1 completes successfully
        Dim commitTran1 = tran1.ContinueWith(commit, TaskContinuationOptions.OnlyOnRanToCompletion)
        ' The following task gets scheduled only if tran1 DOES NOT complete successfully
        Dim rollbackTran1 = tran1.ContinueWith(rollback, TaskContinuationOptions.NotOnRanToCompletion)
        ' For demo purposes, wait for the sample to complete
        commitTran1.Wait()
        ' -----------------------------------------------------------------------------------
        ' Failed transaction - Begin + exception + Rollback 
        Console.WriteLine(vbLf & "Demonstrating a failed transaction")
        ' Initial task
        ' Treated as "fire-and-forget" -- any exceptions will be cleaned up in rollback continuation
        Dim tran2 As Task = Task.Factory.StartNew(failure)
        ' The following task gets scheduled only if tran2 completes successfully
        Dim commitTran2 = tran2.ContinueWith(commit, TaskContinuationOptions.OnlyOnRanToCompletion)
        ' The following task gets scheduled only if tran2 DOES NOT complete successfully
        Dim rollbackTran2 = tran2.ContinueWith(rollback, TaskContinuationOptions.NotOnRanToCompletion)
        ' For demo purposes, wait for the sample to complete
        rollbackTran2.Wait()
    End Sub
End Module
    	

退回 Task<TResult> 的任務在當前任務完成前不會排程執行。 若未符合參數所指定的 continuationOptions 條件,續接任務將被取消而非排程。

public:
generic <typename TResult>
 System::Threading::Tasks::Task<TResult> ^ ContinueWith(Func<System::Threading::Tasks::Task ^, System::Object ^, TResult> ^ continuationFunction, System::Object ^ state, System::Threading::CancellationToken cancellationToken);
public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(Func<System.Threading.Tasks.Task,object,TResult> continuationFunction, object state, System.Threading.CancellationToken cancellationToken);
public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(Func<System.Threading.Tasks.Task,object?,TResult> continuationFunction, object? state, System.Threading.CancellationToken cancellationToken);
member this.ContinueWith : Func<System.Threading.Tasks.Task, obj, 'Result> * obj * System.Threading.CancellationToken -> System.Threading.Tasks.Task<'Result>
Public Function ContinueWith(Of TResult) (continuationFunction As Func(Of Task, Object, TResult), state As Object, cancellationToken As CancellationToken) As Task(Of TResult)
TResult
public:
generic <typename TResult>
 System::Threading::Tasks::Task<TResult> ^ ContinueWith(Func<System::Threading::Tasks::Task ^, System::Object ^, TResult> ^ continuationFunction, System::Object ^ state, System::Threading::Tasks::TaskContinuationOptions continuationOptions);
public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(Func<System.Threading.Tasks.Task,object,TResult> continuationFunction, object state, System.Threading.Tasks.TaskContinuationOptions continuationOptions);
public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(Func<System.Threading.Tasks.Task,object?,TResult> continuationFunction, object? state, System.Threading.Tasks.TaskContinuationOptions continuationOptions);
member this.ContinueWith : Func<System.Threading.Tasks.Task, obj, 'Result> * obj * System.Threading.Tasks.TaskContinuationOptions -> System.Threading.Tasks.Task<'Result>
Public Function ContinueWith(Of TResult) (continuationFunction As Func(Of Task, Object, TResult), state As Object, continuationOptions As TaskContinuationOptions) As Task(Of TResult)
TResult
public:
generic <typename TResult>
 System::Threading::Tasks::Task<TResult> ^ ContinueWith(Func<System::Threading::Tasks::Task ^, TResult> ^ continuationFunction, System::Threading::Tasks::TaskContinuationOptions continuationOptions);
public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(Func<System.Threading.Tasks.Task,TResult> continuationFunction, System.Threading.Tasks.TaskContinuationOptions continuationOptions);
member this.ContinueWith : Func<System.Threading.Tasks.Task, 'Result> * System.Threading.Tasks.TaskContinuationOptions -> System.Threading.Tasks.Task<'Result>
Public Function ContinueWith(Of TResult) (continuationFunction As Func(Of Task, TResult), continuationOptions As TaskContinuationOptions) As Task(Of TResult)
TResult
public:
generic <typename TResult>
 System::Threading::Tasks::Task<TResult> ^ ContinueWith(Func<System::Threading::Tasks::Task ^, TResult> ^ continuationFunction, System::Threading::Tasks::TaskScheduler ^ scheduler);
public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(Func<System.Threading.Tasks.Task,TResult> continuationFunction, System.Threading.Tasks.TaskScheduler scheduler);
member this.ContinueWith : Func<System.Threading.Tasks.Task, 'Result> * System.Threading.Tasks.TaskScheduler -> System.Threading.Tasks.Task<'Result>
Public Function ContinueWith(Of TResult) (continuationFunction As Func(Of Task, TResult), scheduler As TaskScheduler) As Task(Of TResult)
TResult
public:
generic <typename TResult>
 System::Threading::Tasks::Task<TResult> ^ ContinueWith(Func<System::Threading::Tasks::Task ^, TResult> ^ continuationFunction, System::Threading::CancellationToken cancellationToken);
public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(Func<System.Threading.Tasks.Task,TResult> continuationFunction, System.Threading.CancellationToken cancellationToken);
member this.ContinueWith : Func<System.Threading.Tasks.Task, 'Result> * System.Threading.CancellationToken -> System.Threading.Tasks.Task<'Result>
Public Function ContinueWith(Of TResult) (continuationFunction As Func(Of Task, TResult), cancellationToken As CancellationToken) As Task(Of TResult)
TResult
public:
generic <typename TResult>
 System::Threading::Tasks::Task<TResult> ^ ContinueWith(Func<System::Threading::Tasks::Task ^, System::Object ^, TResult> ^ continuationFunction, System::Object ^ state);
public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(Func<System.Threading.Tasks.Task,object,TResult> continuationFunction, object state);
public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(Func<System.Threading.Tasks.Task,object?,TResult> continuationFunction, object? state);
member this.ContinueWith : Func<System.Threading.Tasks.Task, obj, 'Result> * obj -> System.Threading.Tasks.Task<'Result>
Public Function ContinueWith(Of TResult) (continuationFunction As Func(Of Task, Object, TResult), state As Object) As Task(Of TResult)
TResult
public:
generic <typename TResult>
 System::Threading::Tasks::Task<TResult> ^ ContinueWith(Func<System::Threading::Tasks::Task ^, TResult> ^ continuationFunction);
public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(Func<System.Threading.Tasks.Task,TResult> continuationFunction);
member this.ContinueWith : Func<System.Threading.Tasks.Task, 'Result> -> System.Threading.Tasks.Task<'Result>
Public Function ContinueWith(Of TResult) (continuationFunction As Func(Of Task, TResult)) As Task(Of TResult)
TResult // Task.Wait() // Expected results: // A sequence of three unrelated tasks is created and executed in this order - alpha, beta, gamma. // A sequence of three related tasks is created - each task negates its argument and passes is to the next task: 5, -5, 5 is printed. // A sequence of three unrelated tasks is created where tasks have different types. // Documentation: // http://msdn.microsoft.com/library/system.threading.tasks.taskfactory_members(VS.100).aspx static void Main() Action<string> action = (str) => Console.WriteLine("Task={0}, str={1}, Thread={2}", Task.CurrentId, str, Thread.CurrentThread.ManagedThreadId); // Creating a sequence of action tasks (that return no result). Console.WriteLine("Creating a sequence of action tasks (that return no result)"); Task.Factory.StartNew(() => action("alpha")) .ContinueWith(antecendent => action("beta")) // Antecedent data is ignored .ContinueWith(antecendent => action("gamma")) .Wait(); Func<int, int> negate = (n) => Console.WriteLine("Task={0}, n={1}, -n={2}, Thread={3}", Task.CurrentId, n, -n, Thread.CurrentThread.ManagedThreadId); return -n; // Creating a sequence of function tasks where each continuation uses the result from its antecendent Console.WriteLine("\nCreating a sequence of function tasks where each continuation uses the result from its antecendent"); Task<int>.Factory.StartNew(() => negate(5)) .ContinueWith(antecendent => negate(antecendent.Result)) // Antecedent result feeds into continuation .ContinueWith(antecendent => negate(antecendent.Result)) .Wait(); // Creating a sequence of tasks where you can mix and match the types Console.WriteLine("\nCreating a sequence of tasks where you can mix and match the types"); Task<int>.Factory.StartNew(() => negate(6)) .ContinueWith(antecendent => action("x")) .ContinueWith(antecendent => negate(7)) .Wait();
open System
open System.Threading
open System.Threading.Tasks
// Demonstrated features:
// 		Task.Factory
//		Task.ContinueWith()
//		Task.Wait()
// Expected results:
// 		A sequence of three unrelated tasks is created and executed in this order - alpha, beta, gamma.
//		A sequence of three related tasks is created - each task negates its argument and passes is to the next task: 5, -5, 5 is printed.
//		A sequence of three unrelated tasks is created where tasks have different types.
// Documentation:
//		http://msdn.microsoft.com/library/system.threading.tasks.taskfactory_members(VS.100).aspx
let action =
    fun str -> printfn $"Task={Task.CurrentId}, str=%s{str}, Thread={Thread.CurrentThread.ManagedThreadId}"
// Creating a sequence of action tasks (that return no result).
printfn "Creating a sequence of action tasks (that return no result)"
    .Factory
    .StartNew(fun () -> action "alpha")
    .ContinueWith(fun antecendent -> action "beta") // Antecedent data is ignored
    .ContinueWith(fun antecendent -> action "gamma")
    .Wait()
let negate =
    fun n ->
        printfn $"Task={Task.CurrentId}, n={n}, -n={2 - n}, Thread={Thread.CurrentThread.ManagedThreadId}"
// Creating a sequence of function tasks where each continuation uses the result from its antecendent
printfn "\nCreating a sequence of function tasks where each continuation uses the result from its antecendent"
Task<int>
    .Factory.StartNew(fun () -> negate 5)
    .ContinueWith(Func<Task<int>, int>(fun antecedent -> negate antecedent.Result)) // Antecedent result feeds into continuation
    .ContinueWith(Func<Task<int>, int>(fun antecedent -> negate antecedent.Result))
    .Wait()
// Creating a sequence of tasks where you can mix and match the types
printfn "\nCreating a sequence of tasks where you can mix and match the types"
Task<int>
    .Factory.StartNew(fun () -> negate 6)
    .ContinueWith(Action<Task>(fun antecendent -> action "x"))
    .ContinueWith(fun antecendent -> negate 7)
    .Wait()
Imports System.Threading
Imports System.Threading.Tasks
Module ContinuationDemo
    ' Demonstrated features:
    '   Task.Factory
    '   Task.ContinueWith()
    '   Task.Wait()
    ' Expected results:
    '   A sequence of three unrelated tasks is created and executed in this order - alpha, beta, gamma.
    '   A sequence of three related tasks is created - each task negates its argument and passes is to the next task: 5, -5, 5 is printed.
    '   A sequence of three unrelated tasks is created where tasks have different types.
    ' Documentation:
    '   http://msdn.microsoft.com/library/system.threading.tasks.taskfactory_members(VS.100).aspx
    Sub Main()
        Dim action As Action(Of String) = Sub(str) Console.WriteLine("Task={0}, str={1}, Thread={2}", Task.CurrentId, str, Thread.CurrentThread.ManagedThreadId)
        ' Creating a sequence of action tasks (that return no result).
        Console.WriteLine("Creating a sequence of action tasks (that return no result)")
        ' Continuations ignore antecedent data
        Task.Factory.StartNew(Sub() action("alpha")).ContinueWith(Sub(antecendent) action("beta")).ContinueWith(Sub(antecendent) action("gamma")).Wait()
        Dim negate As Func(Of Integer, Integer) = Function(n)
                                                      Console.WriteLine("Task={0}, n={1}, -n={2}, Thread={3}", Task.CurrentId, n, -n, Thread.CurrentThread.ManagedThreadId)
                                                      Return -n
                                                  End Function
        ' Creating a sequence of function tasks where each continuation uses the result from its antecendent
        Console.WriteLine(vbLf & "Creating a sequence of function tasks where each continuation uses the result from its antecendent")
        Task(Of Integer).Factory.StartNew(Function() negate(5)).ContinueWith(Function(antecendent) negate(antecendent.Result)).ContinueWith(Function(antecendent) negate(antecendent.Result)).Wait()
        ' Creating a sequence of tasks where you can mix and match the types
        Console.WriteLine(vbLf & "Creating a sequence of tasks where you can mix and match the types")
        Task(Of Integer).Factory.StartNew(Function() negate(6)).ContinueWith(Sub(antecendent) action("x")).ContinueWith(Function(antecendent) negate(7)).Wait()
    End Sub
End Module
    	

回傳 Task<TResult> 的任務不會排程執行,直到目前任務完成,無論是因成功完成、因未處理異常而錯誤,或因被取消而提前退出。