在上面的示例中,
Result
属性的类型为
string
(Visual Basic 中的
String
)。
不过,在某些情况下,建议在另一个任务中创建任务,再返回嵌套任务。 在这种情况下,封闭任务的
TResult
本身就是任务。 在下面的示例中,Result 属性是 C# 中的
Task<Task<string>>
或 Visual Basic 中的
Task(Of Task(Of String))
。
// Note the type of t and t2.
Task<Task<string>> t = Task.Factory.StartNew(() => DoWorkAsync());
Task<Task<string>> t2 = DoWorkAsync().ContinueWith((s) => DoMoreWorkAsync());
// Outputs: System.Threading.Tasks.Task`1[System.String]
Console.WriteLine(t.Result);
' Note the type of t and t2.
Dim t As Task(Of Task(Of String)) = Task.Run(Function() DoWorkAsync())
Dim t2 As Task(Of Task(Of String)) = DoWorkAsync().ContinueWith(Function(s) DoMoreWorkAsync())
' Outputs: System.Threading.Tasks.Task`1[System.String]
Console.WriteLine(t.Result)
虽然可以编写代码来取消包装外部任务并检索原始任务及其 Result 属性,但此类代码不易编写,因为必须处理异常和取消请求。 在这种情况下,建议使用 Unwrap 扩展方法之一,如下面的示例所示。
// Unwrap the inner task.
Task<string> t3 = DoWorkAsync().ContinueWith((s) => DoMoreWorkAsync()).Unwrap();
// Outputs "More work completed."
Console.WriteLine(t.Result);
' Unwrap the inner task.
Dim t3 As Task(Of String) = DoWorkAsync().ContinueWith(Function(s) DoMoreWorkAsync()).Unwrap()
' Outputs "More work completed."
Console.WriteLine(t.Result)
Unwrap 方法可用于将任何 Task<Task>
或 Task<Task<TResult>>
(Visual Basic 中的 Task(Of Task)
或 Task(Of Task(Of TResult))
)转换为 Task
或 Task<TResult>
(Visual Basic 中的 Task(Of TResult)
)。 新任务完全表示内部嵌套任务,并包含取消状态和所有异常。
下面的示例展示了如何使用 Unwrap 扩展方法。
namespace Unwrap
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
// A program whose only use is to demonstrate Unwrap.
class Program
static void Main()
// An arbitrary threshold value.
byte threshold = 0x40;
// data is a Task<byte[]>
var data = Task<byte[]>.Factory.StartNew(() =>
return GetData();
// We want to return a task so that we can
// continue from it later in the program.
// Without Unwrap: stepTwo is a Task<Task<byte[]>>
// With Unwrap: stepTwo is a Task<byte[]>
var stepTwo = data.ContinueWith((antecedent) =>
return Task<byte>.Factory.StartNew( () => Compute(antecedent.Result));
.Unwrap();
// Without Unwrap: antecedent.Result = Task<byte>
// and the following method will not compile.
// With Unwrap: antecedent.Result = byte and
// we can work directly with the result of the Compute method.
var lastStep = stepTwo.ContinueWith( (antecedent) =>
if (antecedent.Result >= threshold)
return Task.Factory.StartNew( () => Console.WriteLine("Program complete. Final = 0x{0:x} threshold = 0x{1:x}", stepTwo.Result, threshold));
return DoSomeOtherAsynchronousWork(stepTwo.Result, threshold);
lastStep.Wait();
Console.WriteLine("Press any key");
Console.ReadKey();
#region Dummy_Methods
private static byte[] GetData()
Random rand = new Random();
byte[] bytes = new byte[64];
rand.NextBytes(bytes);
return bytes;
static Task DoSomeOtherAsynchronousWork(int i, byte b2)
return Task.Factory.StartNew(() =>
Thread.SpinWait(500000);
Console.WriteLine("Doing more work. Value was <= threshold");
static byte Compute(byte[] data)
byte final = 0;
foreach (byte item in data)
final ^= item;
Console.WriteLine("{0:x}", final);
Console.WriteLine("Done computing");
return final;
#endregion
'How to: Unwrap a Task
Imports System.Threading
Imports System.Threading.Tasks
Module UnwrapATask2
Sub Main()
' An arbitrary threshold value.
Dim threshold As Byte = &H40
' myData is a Task(Of Byte())
Dim myData As Task(Of Byte()) = Task.Factory.StartNew(Function()
Return GetData()
End Function)
' We want to return a task so that we can
' continue from it later in the program.
' Without Unwrap: stepTwo is a Task(Of Task(Of Byte))
' With Unwrap: stepTwo is a Task(Of Byte)
Dim stepTwo = myData.ContinueWith(Function(antecedent)
Return Task.Factory.StartNew(Function()
Return Compute(antecedent.Result)
End Function)
End Function).Unwrap()
Dim lastStep = stepTwo.ContinueWith(Function(antecedent)
Console.WriteLine("Result = {0}", antecedent.Result)
If antecedent.Result >= threshold Then
Return Task.Factory.StartNew(Sub()
Console.WriteLine("Program complete. Final = &H{1:x} threshold = &H{1:x}",
stepTwo.Result, threshold)
End Sub)
Return DoSomeOtherAsynchronousWork(stepTwo.Result, threshold)
End If
End Function)
lastStep.Wait()
Catch ae As AggregateException
For Each ex As Exception In ae.InnerExceptions
Console.WriteLine(ex.Message & ex.StackTrace & ex.GetBaseException.ToString())
End Try
Console.WriteLine("Press any key")
Console.ReadKey()
End Sub
#Region "Dummy_Methods"
Function GetData() As Byte()
Dim rand As Random = New Random()
Dim bytes(64) As Byte
rand.NextBytes(bytes)
Return bytes
End Function
Function DoSomeOtherAsynchronousWork(ByVal i As Integer, ByVal b2 As Byte) As Task
Return Task.Factory.StartNew(Sub()
Thread.SpinWait(500000)
Console.WriteLine("Doing more work. Value was <= threshold.")
End Sub)
End Function
Function Compute(ByVal d As Byte()) As Byte
Dim final As Byte = 0
For Each item As Byte In d
final = final Xor item
Console.WriteLine("{0:x}", final)
Console.WriteLine("Done computing")
Return final
End Function
#End Region
End Module
System.Threading.Tasks.TaskExtensions
基于任务的异步编程