Nasıl yapılır: İç İçe Geçmiş Bir Görevi Sarmalamadan Çıkarma
Bir yöntemden bir görev döndürebilir ve ardından aşağıdaki örnekte gösterildiği gibi bu görevi bekleyebilir veya devam edebilirsiniz:
static Task<string> DoWorkAsync()
{
return Task<String>.Factory.StartNew(() =>
{
//...
return "Work completed.";
});
}
static void StartTask()
{
Task<String> t = DoWorkAsync();
t.Wait();
Console.WriteLine(t.Result);
}
Shared Function DoWorkAsync() As Task(Of String)
Return Task(Of String).Run(Function()
'...
Return "Work completed."
End Function)
End Function
Shared Sub StartTask()
Dim t As Task(Of String) = DoWorkAsync()
t.Wait()
Console.WriteLine(t.Result)
End Sub
Önceki örnekte özelliği Result türündedir string
(String
Visual Basic'te).
Ancak bazı senaryolarda, başka bir görev içinde bir görev oluşturmak ve sonra iç içe görevi döndürmek isteyebilirsiniz. Bu durumda, kapsayan TResult
görevin kendisi bir görevdir. Aşağıdaki örnekte Result özelliği C# veya Task(Of Task(Of String))
Visual Basic'te bir'dirTask<Task<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)
Dış görevi açmak ve özgün görevi ve Result özelliğini almak için kod yazmak mümkün olsa da, özel durumları ve iptal isteklerini işlemeniz gerektiğinden bu tür kodu yazmak kolay değildir. Bu durumda, aşağıdaki örnekte gösterildiği gibi uzantı yöntemlerinden birini Unwrap kullanmanızı öneririz.
// 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)
YöntemlerUnwrap, herhangi birini Task<Task>
veya (Task(Of Task)
veya Task(Of Task(Of TResult))
Visual Basic'te) bir Task
veya Task<Task<TResult>>
Task<TResult>
(Task(Of TResult)
Visual Basic'te) olarak dönüştürmek için kullanılabilir. Yeni görev, iç içe yerleştirilmiş görevi tamamen temsil eder ve iptal durumunu ve tüm özel durumları içerir.
Örnek
Aşağıdaki örnekte uzantı yöntemlerinin Unwrap nasıl kullanılacağı gösterilmektedir.
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));
}
else
{
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)
Else
Return DoSomeOtherAsynchronousWork(stepTwo.Result, threshold)
End If
End Function)
Try
lastStep.Wait()
Catch ae As AggregateException
For Each ex As Exception In ae.InnerExceptions
Console.WriteLine(ex.Message & ex.StackTrace & ex.GetBaseException.ToString())
Next
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)
Next
Console.WriteLine("Done computing")
Return final
End Function
#End Region
End Module
Ayrıca bkz.
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin