Como: A cadeia de várias tarefas com continuação
Na biblioteca de tarefas paralelas, uma tarefa cujo ContinueWith método é invocado é chamado a tarefa antecedente e a tarefa que é definida na ContinueWith método é chamado de continuação. Este exemplo mostra como usar o ContinueWith e ContinueWith métodos para a Task e Task<TResult> classes para especificar uma tarefa que se inicia depois de terminar sua tarefa antecedente.
O exemplo também mostra como especificar uma continuação que será executado somente se o seu antecessor é cancelada.
Esses exemplos demonstram como continuar a partir de uma única tarefa. Você também pode criar uma continuação que é executado após qualquer ou todo um grupo de tarefas, concluir ou são cancelados. Para obter mais informações, consulte TaskContinueWhenAll() e TaskContinueWhenAny().
Exemplo
O DoSimpleContinuation método mostra a sintaxe básica para ContinueWith. Observe que a tarefa antecedente é fornecida como o parâmetro de entrada para a expressão lambda a ContinueWith método. Isso lhe permite avaliar o status da tarefa antecedente antes de executar qualquer trabalho em continuação. Use essa sobrecarga simple ContinueWith Quando você não precisará passar de qualquer estado de uma tarefa para outro.
O DoSimpleContinuationWithState método mostra como usar ContinueWith passar o resultado da tarefa antecedente para a tarefa de continuação.
Imports System.IO
Imports System.Threading
Imports System.Threading.Tasks
Module ContinueWith
Sub Main()
DoSimpleContinuation()
Console.WriteLine("Press any key to exit")
Console.ReadKey()
End Sub
Sub DoSimpleContinuation()
Dim path As String = "C:\users\public\TPLTestFolder\"
Try
Dim firstTask = New Task(Sub() CopyDataIntoTempFolder(path))
Dim secondTask = firstTask.ContinueWith(Sub(t) CreateSummaryFile(path))
firstTask.Start()
Catch e As AggregateException
Console.WriteLine(e.Message)
End Try
End Sub
' A toy function to simulate a workload
Sub CopyDataIntoTempFolder(ByVal path__1 As String)
System.IO.Directory.CreateDirectory(path__1)
Dim rand As New Random()
For x As Integer = 0 To 49
Dim bytes As Byte() = New Byte(999) {}
rand.NextBytes(bytes)
Dim filename As String = Path.GetRandomFileName()
Dim filepath As String = Path.Combine(path__1, filename)
System.IO.File.WriteAllBytes(filepath, bytes)
Next
End Sub
Sub CreateSummaryFile(ByVal path__1 As String)
Dim files As String() = System.IO.Directory.GetFiles(path__1)
Parallel.ForEach(files, Sub(file)
Thread.SpinWait(5000)
End Sub)
System.IO.File.WriteAllText(Path.Combine(path__1, "__SummaryFile.txt"), "did my work")
Console.WriteLine("Done with task2")
End Sub
Sub DoSimpleContinuationWithState()
Dim nums As Integer() = {19, 17, 21, 4, 13, 8, _
12, 7, 3, 5}
Dim f0 = New Task(Of Double)(Function() nums.Average())
Dim f1 = f0.ContinueWith(Function(t) GetStandardDeviation(nums, t.Result))
f0.Start()
Console.WriteLine("the standard deviation is {0}", f1)
End Sub
Function GetStandardDeviation(ByVal values As Integer(), ByVal mean As Double) As Double
Dim d As Double = 0.0R
For Each n In values
d += Math.Pow(mean - n, 2)
Next
Return Math.Sqrt(d / (values.Length - 1))
End Function
End Module
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace ContinueWith
{
class Continuations
{
static void Main()
{
SimpleContinuation();
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
static void SimpleContinuation()
{
string path = @"C:\users\public\TPLTestFolder\";
try
{
var firstTask = new Task(() => CopyDataIntoTempFolder(path));
var secondTask = firstTask.ContinueWith((t) => CreateSummaryFile(path));
firstTask.Start();
}
catch (AggregateException e)
{
Console.WriteLine(e.Message);
}
}
// A toy function to simulate a workload
static void CopyDataIntoTempFolder(string path)
{
System.IO.Directory.CreateDirectory(path);
Random rand = new Random();
for (int x = 0; x < 50; x++)
{
byte[] bytes = new byte[1000];
rand.NextBytes(bytes);
string filename = Path.GetRandomFileName();
string filepath = Path.Combine(path, filename);
System.IO.File.WriteAllBytes(filepath, bytes);
}
}
static void CreateSummaryFile(string path)
{
string[] files = System.IO.Directory.GetFiles(path);
Parallel.ForEach(files, (file) =>
{
Thread.SpinWait(5000);
});
System.IO.File.WriteAllText(Path.Combine(path, "__SummaryFile.txt"), "did my work");
Console.WriteLine("Done with task2");
}
static void SimpleContinuationWithState()
{
int[] nums = { 19, 17, 21, 4, 13, 8, 12, 7, 3, 5 };
var f0 = new Task<double>(() => nums.Average());
var f1 = f0.ContinueWith( t => GetStandardDeviation(nums, t.Result));
f0.Start();
Console.WriteLine("the standard deviation is {0}", f1.Result);
}
private static double GetStandardDeviation(int[] values, double mean)
{
double d = 0.0;
foreach (var n in values)
{
d += Math.Pow(mean - n, 2);
}
return Math.Sqrt(d / (values.Length - 1));
}
}
}
O parâmetro de tipo de Task<TResult> determina o tipo de retorno do delegado. Que retornam o valor é passado para a tarefa de continuação. Um número arbitrário de tarefas pode ser encadeado dessa maneira.
Consulte também
Conceitos
Programação em paralela a.NET Framework
Expressões lambda no PLINQ e TPL