Görev tabanlı zaman uyumsuz programlama
Görev Paralel Kitaplığı (TPL), zaman uyumsuz bir işlemi temsil eden bir görev kavramına dayalıdır. Bazı yollarla, bir görev bir iş parçacığına veya iş öğesine ThreadPool benzer, ancak daha yüksek bir soyutlama düzeyindedir. Görev paralelliği terimi, eşzamanlı olarak çalışan bir veya daha fazla bağımsız görevi ifade eder. Görevler iki adet birincil avantaj sağlar:
Sistem kaynaklarının daha verimli ve daha ölçeklenebilir kullanımı.
Arkadaki görevler, iş parçacığı sayısını belirleyen ve ayar sağlayan ve aktarım hızını en üst düzeye çıkarmak için yük dengeleme sağlayan algoritmalarla geliştirilmiş olan 'a ThreadPool kuyruğa eklenir. Bu, görevleri oldukça basit hale getirir ve hassas paralellik sağlamak için bunlardan çok sayıda oluşturabilirsiniz.
Bir iş parçacığı veya iş öğesi ile mümkün olandan daha programlı denetim.
Görevler ve bunların etrafına yerleşik çatı, bekleme, iptal, devamlılık, sağlam özel durum işleme, ayrıntılı durum, özel zamanlama ve daha fazlasını destekleyen zengin bir API kümesi sağlar.
Bu iki nedenle de TPL, .NET'te çok iş parçacıklı, zaman uyumsuz ve paralel kod yazmak için tercih edilen API'dir.
Görevleri örtülü olarak oluşturma ve çalıştırma
yöntemi, Parallel.Invoke herhangi bir sayıda rastgele deyimi eşzamanlı olarak çalıştırmak için kullanışlı bir yol sağlar. Yalnızca her iş Action öğesi için bir temsilci iletebilirsiniz. Lambda ifadelerini kullanmak, bu temsilcileri oluşturmanın en kolay yoludur. Lambda ifadesi adlandırılmış bir yöntemi çağırabilir veya satır içi kodu sağlayabilir. Aşağıdaki örnek, eşzamanlı olarak Invoke çalıştıran iki görev oluşturan ve başlatan temel bir çağrıyı gösterir. İlk görev adlı bir yöntemi çağıran bir lambda ifadesiyle temsil edildi ve ikinci görev adlı yöntemi çağıran DoSomeWork bir lambda ifadesiyle temsil DoSomeOtherWork edildi.
Not
TPL'de temsilciler tanımlamak için bu belgede lambda ifadeleri kullanılır. C# veya Visual Basic'daki lambda ifadeleri hakkında bilgi sahibi değilsanız bkz. PLINQ ve TPL'de Lambda İfadeleri.
Parallel.Invoke(() => DoSomeWork(), () => DoSomeOtherWork());
Parallel.Invoke(Sub() DoSomeWork(), Sub() DoSomeOtherWork())
Not
tarafından arka Task arkasında oluşturulan örnek sayısı, sağlanan temsilci Invoke sayısına eşit olmayabilir. TPL, özellikle çok sayıda temsilci bulunduğunda, çeşitli iyileştirmeler uygulayabilir.
Daha fazla bilgi için, bkz. How to: Use Parallel.Invoke to Execute Parallel Operations.
Görev yürütme üzerinde daha fazla denetime sahip olmak veya görevden bir değer dönmek için nesnelerle daha açık Task bir şekilde çalışmamız gerekir.
Görevleri açıkça oluşturma ve çalıştırma
Değer etmeyen bir görev sınıfı tarafından temsil System.Threading.Tasks.Task edildi. Bir değer döndüren görev, sınıfından System.Threading.Tasks.Task<TResult> devralan sınıfı tarafından temsil Task edildi. Görev nesnesi altyapı ayrıntılarını işler ve çağrıyı yapan iş parçacığının görevin ömrü boyunca erişebildiği yöntemler ve özellikler sağlar. Örneğin, bir görevin çalışmaya mı, tamamlanmaya mı çalıştırıldı, iptal edildi mi yoksa bir özel durum mu oluşturdu olduğunu belirlemek için herhangi bir zamanda görevin Status özelliğine erişebilirsiniz. Durum bir numaralama TaskStatus ile temsil edildi.
Görev oluşturduğunuzda, görevin yürüteceği kodu kapsülleyen bir kullanıcı temsilcisi verirsiniz. Temsilci adlandırılmış bir temsilci, adsız bir yöntem veya lambda ifadesi olarak ifade edilebilir. Lambda ifadeleri, aşağıdaki örnekte gösterildiği gibi adlandırılmış bir yönteme yapılan çağrıyı içerebilir. Örneğin, konsol modu uygulaması sona ermeden önce görevin yürütülmesinin tamamlandığından emin Task.Wait olmak için yöntemine bir çağrıyı içerir.
using System;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
Thread.CurrentThread.Name = "Main";
// Create a task and supply a user delegate by using a lambda expression.
Task taskA = new Task( () => Console.WriteLine("Hello from taskA."));
// Start the task.
taskA.Start();
// Output a message from the calling thread.
Console.WriteLine("Hello from thread '{0}'.",
Thread.CurrentThread.Name);
taskA.Wait();
}
}
// The example displays output like the following:
// Hello from thread 'Main'.
// Hello from taskA.
Imports System.Threading
Imports System.Threading.Tasks
Module Example
Public Sub Main()
Thread.CurrentThread.Name = "Main"
' Create a task and supply a user delegate by using a lambda expression.
Dim taskA = New Task(Sub() Console.WriteLine("Hello from taskA."))
' Start the task.
taskA.Start()
' Output a message from the calling thread.
Console.WriteLine("Hello from thread '{0}'.",
Thread.CurrentThread.Name)
taskA.Wait()
End Sub
End Module
' The example displays output like the following:
' Hello from thread 'Main'.
' Hello from taskA.
Bir görevi tek bir Task.Run işlemde oluşturmak ve başlatmak için yöntemlerini de kullanabilirsiniz. Görevi yönetmek için yöntemler, geçerli iş parçacığıyla hangi görev zamanlayıcının ilişkili olduğuna Run bakılmaksızın varsayılan görev zamanlayıcıyı kullanır. Yöntemler, görevin oluşturulması ve zamanlaması üzerinde daha fazla denetime ihtiyaç duyulmay olduğunda görevleri oluşturmak ve Run başlatmak için tercih edilen yöntemdir.
using System;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
Thread.CurrentThread.Name = "Main";
// Define and run the task.
Task taskA = Task.Run( () => Console.WriteLine("Hello from taskA."));
// Output a message from the calling thread.
Console.WriteLine("Hello from thread '{0}'.",
Thread.CurrentThread.Name);
taskA.Wait();
}
}
// The example displays output like the following:
// Hello from thread 'Main'.
// Hello from taskA.
Imports System.Threading
Imports System.Threading.Tasks
Module Example
Public Sub Main()
Thread.CurrentThread.Name = "Main"
Dim taskA As Task = Task.Run(Sub() Console.WriteLine("Hello from taskA."))
' Output a message from the calling thread.
Console.WriteLine("Hello from thread '{0}'.",
Thread.CurrentThread.Name)
taskA.Wait()
End Sub
End Module
' The example displays output like the following:
' Hello from thread 'Main'.
' Hello from taskA.
Bir görevi tek bir TaskFactory.StartNew işlemde oluşturmak ve başlatmak için yöntemini de kullanabilirsiniz. Oluşturma ve zamanlama arasında ayrım yapmak zorunda değilseniz ve ek görev oluşturma seçeneklerine veya belirli bir zamanlayıcının kullanımına ihtiyacınız olduğunda ya da aşağıdaki örnekte gösterildiği gibi, özelliği aracılığıyla aldırabilirsiniz göreve ek durum geçmeniz gerekirken bu Task.AsyncState yöntemi kullanın.
using System;
using System.Threading;
using System.Threading.Tasks;
class CustomData
{
public long CreationTime;
public int Name;
public int ThreadNum;
}
public class Example
{
public static void Main()
{
Task[] taskArray = new Task[10];
for (int i = 0; i < taskArray.Length; i++) {
taskArray[i] = Task.Factory.StartNew( (Object obj ) => {
CustomData data = obj as CustomData;
if (data == null)
return;
data.ThreadNum = Thread.CurrentThread.ManagedThreadId;
},
new CustomData() {Name = i, CreationTime = DateTime.Now.Ticks} );
}
Task.WaitAll(taskArray);
foreach (var task in taskArray) {
var data = task.AsyncState as CustomData;
if (data != null)
Console.WriteLine("Task #{0} created at {1}, ran on thread #{2}.",
data.Name, data.CreationTime, data.ThreadNum);
}
}
}
// The example displays output like the following:
// Task #0 created at 635116412924597583 on thread #3.
// Task #1 created at 635116412924607584 on thread #4.
// Task #3 created at 635116412924607584 on thread #4.
// Task #4 created at 635116412924607584 on thread #4.
// Task #2 created at 635116412924607584 on thread #3.
// Task #6 created at 635116412924607584 on thread #3.
// Task #5 created at 635116412924607584 on thread #4.
// Task #8 created at 635116412924607584 on thread #4.
// Task #7 created at 635116412924607584 on thread #3.
// Task #9 created at 635116412924607584 on thread #4.
Imports System.Threading
Imports System.Threading.Tasks
Class CustomData
Public CreationTime As Long
Public Name As Integer
Public ThreadNum As Integer
End Class
Module Example
Public Sub Main()
Dim taskArray(9) As Task
For i As Integer = 0 To taskArray.Length - 1
taskArray(i) = Task.Factory.StartNew(Sub(obj As Object)
Dim data As CustomData = TryCast(obj, CustomData)
If data Is Nothing Then Return
data.ThreadNum = Thread.CurrentThread.ManagedThreadId
End Sub,
New CustomData With {.Name = i, .CreationTime = DateTime.Now.Ticks})
Next
Task.WaitAll(taskArray)
For Each task In taskArray
Dim data = TryCast(task.AsyncState, CustomData)
If data IsNot Nothing Then
Console.WriteLine("Task #{0} created at {1}, ran on thread #{2}.",
data.Name, data.CreationTime, data.ThreadNum)
End If
Next
End Sub
End Module
' The example displays output like the following:
' Task #0 created at 635116451245250515, ran on thread #3, RanToCompletion
' Task #1 created at 635116451245270515, ran on thread #4, RanToCompletion
' Task #2 created at 635116451245270515, ran on thread #3, RanToCompletion
' Task #3 created at 635116451245270515, ran on thread #3, RanToCompletion
' Task #4 created at 635116451245270515, ran on thread #3, RanToCompletion
' Task #5 created at 635116451245270515, ran on thread #3, RanToCompletion
' Task #6 created at 635116451245270515, ran on thread #3, RanToCompletion
' Task #7 created at 635116451245270515, ran on thread #3, RanToCompletion
' Task #8 created at 635116451245270515, ran on thread #3, RanToCompletion
' Task #9 created at 635116451245270515, ran on thread #3, RanToCompletion
Taskve Task<TResult> her biri varsayılan örneğini Factory döndüren statik bir özelliği ortaya TaskFactory çıkarır, böylece yöntemini olarak çağırabilirsiniz. Task.Factory.StartNew() Ayrıca, aşağıdaki örnekte görevler türünde olduğundan, her biri hesaplamanın sonucu System.Threading.Tasks.Task<TResult> Task<TResult>.Result içeren bir genel özelliğine sahip olur. Görevler zaman uyumsuz olarak çalışır ve herhangi bir sırada tamamlanabilir. Hesaplama Result bitmeden önce özelliğine erişilirse, değer kullanılabilir olana kadar özelliği çağıran iş parçacığını engeller.
using System;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
Task<Double>[] taskArray = { Task<Double>.Factory.StartNew(() => DoComputation(1.0)),
Task<Double>.Factory.StartNew(() => DoComputation(100.0)),
Task<Double>.Factory.StartNew(() => DoComputation(1000.0)) };
var results = new Double[taskArray.Length];
Double sum = 0;
for (int i = 0; i < taskArray.Length; i++) {
results[i] = taskArray[i].Result;
Console.Write("{0:N1} {1}", results[i],
i == taskArray.Length - 1 ? "= " : "+ ");
sum += results[i];
}
Console.WriteLine("{0:N1}", sum);
}
private static Double DoComputation(Double start)
{
Double sum = 0;
for (var value = start; value <= start + 10; value += .1)
sum += value;
return sum;
}
}
// The example displays the following output:
// 606.0 + 10,605.0 + 100,495.0 = 111,706.0
Imports System.Threading.Tasks
Module Example
Public Sub Main()
Dim taskArray() = {Task(Of Double).Factory.StartNew(Function() DoComputation(1.0)),
Task(Of Double).Factory.StartNew(Function() DoComputation(100.0)),
Task(Of Double).Factory.StartNew(Function() DoComputation(1000.0))}
Dim results(taskArray.Length - 1) As Double
Dim sum As Double
For i As Integer = 0 To taskArray.Length - 1
results(i) = taskArray(i).Result
Console.Write("{0:N1} {1}", results(i),
If(i = taskArray.Length - 1, "= ", "+ "))
sum += results(i)
Next
Console.WriteLine("{0:N1}", sum)
End Sub
Private Function DoComputation(start As Double) As Double
Dim sum As Double
For value As Double = start To start + 10 Step .1
sum += value
Next
Return sum
End Function
End Module
' The example displays the following output:
' 606.0 + 10,605.0 + 100,495.0 = 111,706.0
Daha fazla bilgi için, bkz. How to: Return a Value from a Task.
Temsilci oluşturmak için lambda ifadesini kullandığınızda, kaynak kodunuzun o noktasında görünür durumda olan tüm değişkenlere erişebilirsiniz. Ancak bazı durumlarda, çoğunlukla da döngülerde, bir lambda değişkeni beklenen şekilde yakalamaz. Her yinelemeden sonra oluşturduğu değeri değil, yalnızca son değeri yakalar. Aşağıdaki örnek, sorunu gösterir. Bir döngü sayacını bir nesnenin örneğini alan ve döngü sayacını nesnenin tanımlayıcısı olarak kullanan bir lambda CustomData ifadesine iletir. Örnekteki çıktıda da olduğu gibi her CustomData nesne aynı tanımlayıcıya sahip.
using System;
using System.Threading;
using System.Threading.Tasks;
class CustomData
{
public long CreationTime;
public int Name;
public int ThreadNum;
}
public class Example
{
public static void Main()
{
// Create the task object by using an Action(Of Object) to pass in the loop
// counter. This produces an unexpected result.
Task[] taskArray = new Task[10];
for (int i = 0; i < taskArray.Length; i++) {
taskArray[i] = Task.Factory.StartNew( (Object obj) => {
var data = new CustomData() {Name = i, CreationTime = DateTime.Now.Ticks};
data.ThreadNum = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("Task #{0} created at {1} on thread #{2}.",
data.Name, data.CreationTime, data.ThreadNum);
},
i );
}
Task.WaitAll(taskArray);
}
}
// The example displays output like the following:
// Task #10 created at 635116418427727841 on thread #4.
// Task #10 created at 635116418427737842 on thread #4.
// Task #10 created at 635116418427737842 on thread #4.
// Task #10 created at 635116418427737842 on thread #4.
// Task #10 created at 635116418427737842 on thread #4.
// Task #10 created at 635116418427737842 on thread #4.
// Task #10 created at 635116418427727841 on thread #3.
// Task #10 created at 635116418427747843 on thread #3.
// Task #10 created at 635116418427747843 on thread #3.
// Task #10 created at 635116418427737842 on thread #4.
Imports System.Threading
Imports System.Threading.Tasks
Class CustomData
Public CreationTime As Long
Public Name As Integer
Public ThreadNum As Integer
End Class
Module Example
Public Sub Main()
' Create the task object by using an Action(Of Object) to pass in the loop
' counter. This produces an unexpected result.
Dim taskArray(9) As Task
For i As Integer = 0 To taskArray.Length - 1
taskArray(i) = Task.Factory.StartNew(Sub(obj As Object)
Dim data As New CustomData With {.Name = i, .CreationTime = DateTime.Now.Ticks}
data.ThreadNum = Thread.CurrentThread.ManagedThreadId
Console.WriteLine("Task #{0} created at {1} on thread #{2}.",
data.Name, data.CreationTime, data.ThreadNum)
End Sub,
i)
Next
Task.WaitAll(taskArray)
End Sub
End Module
' The example displays output like the following:
' Task #10 created at 635116418427727841 on thread #4.
' Task #10 created at 635116418427737842 on thread #4.
' Task #10 created at 635116418427737842 on thread #4.
' Task #10 created at 635116418427737842 on thread #4.
' Task #10 created at 635116418427737842 on thread #4.
' Task #10 created at 635116418427737842 on thread #4.
' Task #10 created at 635116418427727841 on thread #3.
' Task #10 created at 635116418427747843 on thread #3.
' Task #10 created at 635116418427747843 on thread #3.
' Task #10 created at 635116418427737842 on thread #4.
Oluşturucusu aracılığıyla göreve durum nesnesi döndürerek her yinelemede değere erişebilirsiniz. Aşağıdaki örnek, lambda ifadesine geçirilen nesnesini oluştururken döngü sayacını kullanarak önceki CustomData örneği değiştiren bir örnektir. Örnekteki çıktıda da olduğu gibi, her nesne artık nesnenin örneği oluşturma zamanında döngü sayacının değerine CustomData göre benzersiz bir tanımlayıcıya sahip.
using System;
using System.Threading;
using System.Threading.Tasks;
class CustomData
{
public long CreationTime;
public int Name;
public int ThreadNum;
}
public class Example
{
public static void Main()
{
// Create the task object by using an Action(Of Object) to pass in custom data
// to the Task constructor. This is useful when you need to capture outer variables
// from within a loop.
Task[] taskArray = new Task[10];
for (int i = 0; i < taskArray.Length; i++) {
taskArray[i] = Task.Factory.StartNew( (Object obj ) => {
CustomData data = obj as CustomData;
if (data == null)
return;
data.ThreadNum = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("Task #{0} created at {1} on thread #{2}.",
data.Name, data.CreationTime, data.ThreadNum);
},
new CustomData() {Name = i, CreationTime = DateTime.Now.Ticks} );
}
Task.WaitAll(taskArray);
}
}
// The example displays output like the following:
// Task #0 created at 635116412924597583 on thread #3.
// Task #1 created at 635116412924607584 on thread #4.
// Task #3 created at 635116412924607584 on thread #4.
// Task #4 created at 635116412924607584 on thread #4.
// Task #2 created at 635116412924607584 on thread #3.
// Task #6 created at 635116412924607584 on thread #3.
// Task #5 created at 635116412924607584 on thread #4.
// Task #8 created at 635116412924607584 on thread #4.
// Task #7 created at 635116412924607584 on thread #3.
// Task #9 created at 635116412924607584 on thread #4.
Imports System.Threading
Imports System.Threading.Tasks
Class CustomData
Public CreationTime As Long
Public Name As Integer
Public ThreadNum As Integer
End Class
Module Example
Public Sub Main()
' Create the task object by using an Action(Of Object) to pass in custom data
' to the Task constructor. This is useful when you need to capture outer variables
' from within a loop.
Dim taskArray(9) As Task
For i As Integer = 0 To taskArray.Length - 1
taskArray(i) = Task.Factory.StartNew(Sub(obj As Object)
Dim data As CustomData = TryCast(obj, CustomData)
If data Is Nothing Then Return
data.ThreadNum = Thread.CurrentThread.ManagedThreadId
Console.WriteLine("Task #{0} created at {1} on thread #{2}.",
data.Name, data.CreationTime, data.ThreadNum)
End Sub,
New CustomData With {.Name = i, .CreationTime = DateTime.Now.Ticks})
Next
Task.WaitAll(taskArray)
End Sub
End Module
' The example displays output like the following:
' Task #0 created at 635116412924597583 on thread #3.
' Task #1 created at 635116412924607584 on thread #4.
' Task #3 created at 635116412924607584 on thread #4.
' Task #4 created at 635116412924607584 on thread #4.
' Task #2 created at 635116412924607584 on thread #3.
' Task #6 created at 635116412924607584 on thread #3.
' Task #5 created at 635116412924607584 on thread #4.
' Task #8 created at 635116412924607584 on thread #4.
' Task #7 created at 635116412924607584 on thread #3.
' Task #9 created at 635116412924607584 on thread #4.
Bu durum, görev temsilcisine bağımsız değişken olarak geçirilir ve özelliği kullanılarak görev nesnesinden Task.AsyncState erişilebilir. Aşağıdaki örnek, önceki örneğin bir çeşididir. Lambda AsyncState ifadesine geçirilen nesnelerle CustomData ilgili bilgileri görüntülemek için özelliğini kullanır.
using System;
using System.Threading;
using System.Threading.Tasks;
class CustomData
{
public long CreationTime;
public int Name;
public int ThreadNum;
}
public class Example
{
public static void Main()
{
Task[] taskArray = new Task[10];
for (int i = 0; i < taskArray.Length; i++) {
taskArray[i] = Task.Factory.StartNew( (Object obj ) => {
CustomData data = obj as CustomData;
if (data == null)
return;
data.ThreadNum = Thread.CurrentThread.ManagedThreadId;
},
new CustomData() {Name = i, CreationTime = DateTime.Now.Ticks} );
}
Task.WaitAll(taskArray);
foreach (var task in taskArray) {
var data = task.AsyncState as CustomData;
if (data != null)
Console.WriteLine("Task #{0} created at {1}, ran on thread #{2}.",
data.Name, data.CreationTime, data.ThreadNum);
}
}
}
// The example displays output like the following:
// Task #0 created at 635116412924597583 on thread #3.
// Task #1 created at 635116412924607584 on thread #4.
// Task #3 created at 635116412924607584 on thread #4.
// Task #4 created at 635116412924607584 on thread #4.
// Task #2 created at 635116412924607584 on thread #3.
// Task #6 created at 635116412924607584 on thread #3.
// Task #5 created at 635116412924607584 on thread #4.
// Task #8 created at 635116412924607584 on thread #4.
// Task #7 created at 635116412924607584 on thread #3.
// Task #9 created at 635116412924607584 on thread #4.
Imports System.Threading
Imports System.Threading.Tasks
Class CustomData
Public CreationTime As Long
Public Name As Integer
Public ThreadNum As Integer
End Class
Module Example
Public Sub Main()
Dim taskArray(9) As Task
For i As Integer = 0 To taskArray.Length - 1
taskArray(i) = Task.Factory.StartNew(Sub(obj As Object)
Dim data As CustomData = TryCast(obj, CustomData)
If data Is Nothing Then Return
data.ThreadNum = Thread.CurrentThread.ManagedThreadId
End Sub,
New CustomData With {.Name = i, .CreationTime = DateTime.Now.Ticks})
Next
Task.WaitAll(taskArray)
For Each task In taskArray
Dim data = TryCast(task.AsyncState, CustomData)
If data IsNot Nothing Then
Console.WriteLine("Task #{0} created at {1}, ran on thread #{2}.",
data.Name, data.CreationTime, data.ThreadNum)
End If
Next
End Sub
End Module
' The example displays output like the following:
' Task #0 created at 635116451245250515, ran on thread #3, RanToCompletion
' Task #1 created at 635116451245270515, ran on thread #4, RanToCompletion
' Task #2 created at 635116451245270515, ran on thread #3, RanToCompletion
' Task #3 created at 635116451245270515, ran on thread #3, RanToCompletion
' Task #4 created at 635116451245270515, ran on thread #3, RanToCompletion
' Task #5 created at 635116451245270515, ran on thread #3, RanToCompletion
' Task #6 created at 635116451245270515, ran on thread #3, RanToCompletion
' Task #7 created at 635116451245270515, ran on thread #3, RanToCompletion
' Task #8 created at 635116451245270515, ran on thread #3, RanToCompletion
' Task #9 created at 635116451245270515, ran on thread #3, RanToCompletion
Görev Kimliği
Her görev, bir uygulama etki alanında benzersiz olarak tanımlayan bir tamsayı kimliği alır ve özelliği kullanılarak Task.Id erişilebilir. Kimlik, hata ayıklayıcısı Paralel Yığınları ve Görevleri Visual Studio görev bilgilerini görüntülemek için kullanışlıdır. Kimlik gecikmeli olarak oluşturulur, yani istenene kadar oluşturulmaz; bu nedenle, program her çalıştırıldığında bir görevin farklı bir kimliği olabilir. Hata ayıklayıcıda görev kimliklerini görüntüleme hakkında daha fazla bilgi için bkz. Görevler Penceresini Kullanma ve Paralel Yığınlar Penceresini Kullanma.
Görev oluşturma seçenekleri
Görev oluşturan çoğu API, parametre kabul eden aşırı yüklemeler TaskCreationOptions sağlar. Bu seçeneklerden birini veya daha fazlasını belirterek, görev zamanlayıcıya görevi iş parçacığı havuzunda nasıl zamanlay olduğunu söylersiniz. Seçenekler bitwise OR işlemi kullanılarak birleştirilmiş olabilir.
Aşağıdaki örnekte, ve seçeneklerine sahip bir LongRunning görev PreferFairness gösterir.
var task3 = new Task(() => MyLongRunningMethod(),
TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness);
task3.Start();
Dim task3 = New Task(Sub() MyLongRunningMethod(),
TaskCreationOptions.LongRunning Or TaskCreationOptions.PreferFairness)
task3.Start()
Görevler, iş parçacıkları ve kültür
Her iş parçacığı, sırasıyla ve özellikleri tarafından tanımlanan ilişkili bir Thread.CurrentCulture kültüre ve Thread.CurrentUICulture kullanıcı arabirimi kültürüne sahiptir. Bir iş parçacığının kültürü biçimlendirme, ayrıştırma, sıralama ve dize karşılaştırma gibi işlemlerde kullanılır. Kaynak aramada iş parçacığının kullanıcı arabirimi kültürü kullanılır.
ve özelliklerini kullanarak bir uygulama etki alanındaki tüm iş parçacıkları için varsayılan bir kültür belirtmedikçe, bir iş parçacığının varsayılan kültürü ve kullanıcı arabirimi kültürü sistem kültürü CultureInfo.DefaultThreadCurrentCulture CultureInfo.DefaultThreadCurrentUICulture tarafından tanımlanır. Bir iş parçacığının kültürünü açıkça ayarp yeni bir iş parçacığını başlatıyorsanız, yeni iş parçacığı çağıran iş parçacığının kültürünü devralmaz; bunun yerine, kültürü varsayılan sistem kültürüdür. Ancak görev tabanlı programlamada görevler, görev farklı bir iş parçacığında zaman uyumsuz olarak çalışıyor olsa bile çağıran iş parçacığının kültürünü kullanır.
Aşağıdaki örnek basit bir çizim sağlar. Uygulamanın geçerli kültürünü Fransızca (Fransa) (veya zaten geçerli kültür Fransızca (Fransa) ise İngilizce (Fransa) olarak Birleşik Devletler) değiştirir. Ardından, yeni kültürde para formatDelegate birimi değerleri olarak biçimlendirilmiş bazı sayıları döndüren adlı bir temsilci çağırır. Temsilcinin bir görev tarafından zaman uyumlu veya zaman uyumsuz olarak çağrılıp çağrılmaysa, görev çağıran iş parçacığının kültürünü kullanır.
using System;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
decimal[] values = { 163025412.32m, 18905365.59m };
string formatString = "C2";
Func<String> formatDelegate = () => { string output = String.Format("Formatting using the {0} culture on thread {1}.\n",
CultureInfo.CurrentCulture.Name,
Thread.CurrentThread.ManagedThreadId);
foreach (var value in values)
output += String.Format("{0} ", value.ToString(formatString));
output += Environment.NewLine;
return output;
};
Console.WriteLine("The example is running on thread {0}",
Thread.CurrentThread.ManagedThreadId);
// Make the current culture different from the system culture.
Console.WriteLine("The current culture is {0}",
CultureInfo.CurrentCulture.Name);
if (CultureInfo.CurrentCulture.Name == "fr-FR")
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
else
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
Console.WriteLine("Changed the current culture to {0}.\n",
CultureInfo.CurrentCulture.Name);
// Execute the delegate synchronously.
Console.WriteLine("Executing the delegate synchronously:");
Console.WriteLine(formatDelegate());
// Call an async delegate to format the values using one format string.
Console.WriteLine("Executing a task asynchronously:");
var t1 = Task.Run(formatDelegate);
Console.WriteLine(t1.Result);
Console.WriteLine("Executing a task synchronously:");
var t2 = new Task<String>(formatDelegate);
t2.RunSynchronously();
Console.WriteLine(t2.Result);
}
}
// The example displays the following output:
// The example is running on thread 1
// The current culture is en-US
// Changed the current culture to fr-FR.
//
// Executing the delegate synchronously:
// Formatting using the fr-FR culture on thread 1.
// 163 025 412,32 € 18 905 365,59 €
//
// Executing a task asynchronously:
// Formatting using the fr-FR culture on thread 3.
// 163 025 412,32 € 18 905 365,59 €
//
// Executing a task synchronously:
// Formatting using the fr-FR culture on thread 1.
// 163 025 412,32 € 18 905 365,59 €
Imports System.Globalization
Imports System.Threading
Module Example
Public Sub Main()
Dim values() As Decimal = {163025412.32D, 18905365.59D}
Dim formatString As String = "C2"
Dim formatDelegate As Func(Of String) = Function()
Dim output As String = String.Format("Formatting using the {0} culture on thread {1}.",
CultureInfo.CurrentCulture.Name,
Thread.CurrentThread.ManagedThreadId)
output += Environment.NewLine
For Each value In values
output += String.Format("{0} ", value.ToString(formatString))
Next
output += Environment.NewLine
Return output
End Function
Console.WriteLine("The example is running on thread {0}",
Thread.CurrentThread.ManagedThreadId)
' Make the current culture different from the system culture.
Console.WriteLine("The current culture is {0}",
CultureInfo.CurrentCulture.Name)
If CultureInfo.CurrentCulture.Name = "fr-FR" Then
Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
Else
Thread.CurrentThread.CurrentCulture = New CultureInfo("fr-FR")
End If
Console.WriteLine("Changed the current culture to {0}.",
CultureInfo.CurrentCulture.Name)
Console.WriteLine()
' Execute the delegate synchronously.
Console.WriteLine("Executing the delegate synchronously:")
Console.WriteLine(formatDelegate())
' Call an async delegate to format the values using one format string.
Console.WriteLine("Executing a task asynchronously:")
Dim t1 = Task.Run(formatDelegate)
Console.WriteLine(t1.Result)
Console.WriteLine("Executing a task synchronously:")
Dim t2 = New Task(Of String)(formatDelegate)
t2.RunSynchronously()
Console.WriteLine(t2.Result)
End Sub
End Module
' The example displays the following output:
'
' The example is running on thread 1
' The current culture is en-US
' Changed the current culture to fr-FR.
'
' Executing the delegate synchronously:
' Formatting Imports the fr-FR culture on thread 1.
' 163 025 412,32 € 18 905 365,59 €
'
' Executing a task asynchronously:
' Formatting Imports the fr-FR culture on thread 3.
' 163 025 412,32 € 18 905 365,59 €
'
' Executing a task synchronously:
' Formatting Imports the fr-FR culture on thread 1.
' 163 025 412,32 € 18 905 365,59 €
Not
.NET Framework 4.6'dan önceki .NET Framework sürümlerinde, bir görevin kültürü çağıran iş parçacığının kültürü değil üzerinde çalıştır olduğu iş parçacığının kültürü tarafından belirlenir. Zaman uyumsuz görevler için bu, görev tarafından kullanılan kültürün çağıran iş parçacığının kültürüne göre farklı olduğu anlamına gelir.
Zaman uyumsuz görevler ve kültür hakkında daha fazla bilgi için konunun "Kültür ve zaman uyumsuz görev tabanlı işlemler" bölümüne CultureInfo bakın.
Görev devamlılıkları oluşturma
ve Task.ContinueWith Task<TResult>.ContinueWith yöntemleri, bir görevi, bu görev sona geldiğinde başlatan bir görev belirtmenize izin verir. Devamlılık görevinin temsilcisine, önceki görevin durumunu inceley etmesi için bir başvuru geçirildi ve özelliğin değeri alınarak devamlılık girdisi olarak Task<TResult>.Result antecedent çıktısını kullanabilir.
Aşağıdaki örnekte, görev getData yöntemine yapılan bir çağrı ile TaskFactory.StartNew<TResult>(Func<TResult>) başlatıldı. processDataGörev sona geldiğinde otomatik olarak başlatılır ve sona geldiğinde getData displayData processData başlatılır. getData , görevin özelliği aracılığıyla görev tarafından processData erişilebilen bir getData tamsayı dizisi Task<TResult>.Result oluşturur. Görev, bu diziyi işler ve türü yöntemine geçirilen lambda ifadesinin dönüş processData türünden elde edilen sonucu Task<TResult>.ContinueWith<TNewResult>(Func<Task<TResult>,TNewResult>) döndürür. Görev sona geldiğinde otomatik olarak yürütülür ve lambda ifadesi tarafından döndürülen nesneye görevin özelliği displayData processData aracılığıyla Tuple<T1,T2,T3> processData displayData processData Task<TResult>.Result erişilebilir. Görev, görevin sonucu alır ve türü benzer şekilde ortaya çıkan ve özelliğinde program için kullanılabilir yapılan bir displayData processData sonuç Result üretir.
using System;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
var getData = Task.Factory.StartNew(() => {
Random rnd = new Random();
int[] values = new int[100];
for (int ctr = 0; ctr <= values.GetUpperBound(0); ctr++)
values[ctr] = rnd.Next();
return values;
} );
var processData = getData.ContinueWith((x) => {
int n = x.Result.Length;
long sum = 0;
double mean;
for (int ctr = 0; ctr <= x.Result.GetUpperBound(0); ctr++)
sum += x.Result[ctr];
mean = sum / (double) n;
return Tuple.Create(n, sum, mean);
} );
var displayData = processData.ContinueWith((x) => {
return String.Format("N={0:N0}, Total = {1:N0}, Mean = {2:N2}",
x.Result.Item1, x.Result.Item2,
x.Result.Item3);
} );
Console.WriteLine(displayData.Result);
}
}
// The example displays output similar to the following:
// N=100, Total = 110,081,653,682, Mean = 1,100,816,536.82
Imports System.Threading.Tasks
Module Example
Public Sub Main()
Dim getData = Task.Factory.StartNew(Function()
Dim rnd As New Random()
Dim values(99) As Integer
For ctr = 0 To values.GetUpperBound(0)
values(ctr) = rnd.Next()
Next
Return values
End Function)
Dim processData = getData.ContinueWith(Function(x)
Dim n As Integer = x.Result.Length
Dim sum As Long
Dim mean As Double
For ctr = 0 To x.Result.GetUpperBound(0)
sum += x.Result(ctr)
Next
mean = sum / n
Return Tuple.Create(n, sum, mean)
End Function)
Dim displayData = processData.ContinueWith(Function(x)
Return String.Format("N={0:N0}, Total = {1:N0}, Mean = {2:N2}",
x.Result.Item1, x.Result.Item2,
x.Result.Item3)
End Function)
Console.WriteLine(displayData.Result)
End Sub
End Module
' The example displays output like the following:
' N=100, Total = 110,081,653,682, Mean = 1,100,816,536.82
bir örnek yöntemi olduğundan, her bir yöntem için bir nesne örneği oluşturma yerine yöntem çağrılarını Task.ContinueWith Task<TResult> birbirine zincirleme. Aşağıdaki örnek, yöntemine yapılan çağrılara zincir takması dışında, önceki örnekle işlevsel olarak Task.ContinueWith aynıdır. Yöntem çağrıları Task<TResult> zinciri tarafından döndürülen nesnenin son devamlılık görevi olduğunu unutmayın.
using System;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
var displayData = Task.Factory.StartNew(() => {
Random rnd = new Random();
int[] values = new int[100];
for (int ctr = 0; ctr <= values.GetUpperBound(0); ctr++)
values[ctr] = rnd.Next();
return values;
} ).
ContinueWith((x) => {
int n = x.Result.Length;
long sum = 0;
double mean;
for (int ctr = 0; ctr <= x.Result.GetUpperBound(0); ctr++)
sum += x.Result[ctr];
mean = sum / (double) n;
return Tuple.Create(n, sum, mean);
} ).
ContinueWith((x) => {
return String.Format("N={0:N0}, Total = {1:N0}, Mean = {2:N2}",
x.Result.Item1, x.Result.Item2,
x.Result.Item3);
} );
Console.WriteLine(displayData.Result);
}
}
// The example displays output similar to the following:
// N=100, Total = 110,081,653,682, Mean = 1,100,816,536.82
Imports System.Threading.Tasks
Module Example
Public Sub Main()
Dim displayData = Task.Factory.StartNew(Function()
Dim rnd As New Random()
Dim values(99) As Integer
For ctr = 0 To values.GetUpperBound(0)
values(ctr) = rnd.Next()
Next
Return values
End Function). _
ContinueWith(Function(x)
Dim n As Integer = x.Result.Length
Dim sum As Long
Dim mean As Double
For ctr = 0 To x.Result.GetUpperBound(0)
sum += x.Result(ctr)
Next
mean = sum / n
Return Tuple.Create(n, sum, mean)
End Function). _
ContinueWith(Function(x)
Return String.Format("N={0:N0}, Total = {1:N0}, Mean = {2:N2}",
x.Result.Item1, x.Result.Item2,
x.Result.Item3)
End Function)
Console.WriteLine(displayData.Result)
End Sub
End Module
' The example displays output like the following:
' N=100, Total = 110,081,653,682, Mean = 1,100,816,536.82
ve ContinueWhenAll ContinueWhenAny yöntemleri, birden çok görevden devam etmek için olanak sağlar.
Daha fazla bilgi için bkz. Devamlılık Görevlerini Kullanarak Görevleri Zincirleme.
Ayrılmış alt görevler oluşturma
Bir görevde çalışan kullanıcı kodu yeni bir görev oluşturduğunda ve seçeneğini belirtmezken, yeni görev üst görevle özel bir AttachedToParent şekilde eşitlenmez. Bu eşitlenmiş olmayan görev türü ayrılmış iç içe geçmiş görev veya ayrılmış alt görev olarak çağrılır. Aşağıdaki örnek, bağlantısı kesik bir tane alt görev oluşturan bir üst görevi gösterir.
var outer = Task.Factory.StartNew(() =>
{
Console.WriteLine("Outer task beginning.");
var child = Task.Factory.StartNew(() =>
{
Thread.SpinWait(5000000);
Console.WriteLine("Detached task completed.");
});
});
outer.Wait();
Console.WriteLine("Outer task completed.");
// The example displays the following output:
// Outer task beginning.
// Outer task completed.
// Detached task completed.
Dim outer = Task.Factory.StartNew(Sub()
Console.WriteLine("Outer task beginning.")
Dim child = Task.Factory.StartNew(Sub()
Thread.SpinWait(5000000)
Console.WriteLine("Detached task completed.")
End Sub)
End Sub)
outer.Wait()
Console.WriteLine("Outer task completed.")
' The example displays the following output:
' Outer task beginning.
' Outer task completed.
' Detached child completed.
Üst görevin, ayrılmış alt görevin tamamlanmasını beklemediğine dikkat edin.
Alt görevler oluşturma
Bir görevde çalışan kullanıcı kodu seçeneğiyle bir görev oluşturduğunda, yeni görev üst görevin bağlı AttachedToParent alt görevi olarak bilinir. Üst görev bağlı tüm alt görevlerin bitmelerini örtülü olarak bekleyeceği için, yapılandırılmış görev paralelliği ifade AttachedToParent etmek için seçeneğini kullanabilirsiniz. Aşağıdaki örnek, on tane bağlı alt görev oluşturan bir üst görevi gösterir. Örnek, üst görevin bitip bitimini beklemek için yöntemini çağırsa da, ekli alt görevlerin tamamlandıktan sonra açıkça Task.Wait beklemesi gerek olmadığını unutmayın.
using System;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
var parent = Task.Factory.StartNew(() => {
Console.WriteLine("Parent task beginning.");
for (int ctr = 0; ctr < 10; ctr++) {
int taskNo = ctr;
Task.Factory.StartNew((x) => {
Thread.SpinWait(5000000);
Console.WriteLine("Attached child #{0} completed.",
x);
},
taskNo, TaskCreationOptions.AttachedToParent);
}
});
parent.Wait();
Console.WriteLine("Parent task completed.");
}
}
// The example displays output like the following:
// Parent task beginning.
// Attached child #9 completed.
// Attached child #0 completed.
// Attached child #8 completed.
// Attached child #1 completed.
// Attached child #7 completed.
// Attached child #2 completed.
// Attached child #6 completed.
// Attached child #3 completed.
// Attached child #5 completed.
// Attached child #4 completed.
// Parent task completed.
Imports System.Threading
Imports System.Threading.Tasks
Module Example
Public Sub Main()
Dim parent = Task.Factory.StartNew(Sub()
Console.WriteLine("Parent task beginning.")
For ctr As Integer = 0 To 9
Dim taskNo As Integer = ctr
Task.Factory.StartNew(Sub(x)
Thread.SpinWait(5000000)
Console.WriteLine("Attached child #{0} completed.",
x)
End Sub,
taskNo, TaskCreationOptions.AttachedToParent)
Next
End Sub)
parent.Wait()
Console.WriteLine("Parent task completed.")
End Sub
End Module
' The example displays output like the following:
' Parent task beginning.
' Attached child #9 completed.
' Attached child #0 completed.
' Attached child #8 completed.
' Attached child #1 completed.
' Attached child #7 completed.
' Attached child #2 completed.
' Attached child #6 completed.
' Attached child #3 completed.
' Attached child #5 completed.
' Attached child #4 completed.
' Parent task completed.
Bir üst görev, diğer TaskCreationOptions.DenyChildAttach görevlerin üst göreve iliştirmelerini önlemek için seçeneğini kullanabilir. Daha fazla bilgi için bkz. Ekli ve Ayrılmış Alt Görevler.
Görevlerin tamam bekleyenler
System.Threading.Tasks.Taskve System.Threading.Tasks.Task<TResult> türleri, bir görevin Task.Wait bitimini beklemeniz için birkaç yöntem aşırı yüklemesi sağlar. Ayrıca, statik ve yöntemlerin aşırı yüklemeleri, bir görev dizisinin herhangi birini veya hepsini Task.WaitAll Task.WaitAny beklemenize izin verir.
Genellikle, aşağıdaki nedenlerden biri için beklemeniz gerekir:
Ana iş parçacığı, bir göreve göre hesaplanan nihai sonuca bağlıdır.
Görevden oluşturulan özel durumları işlemeniz gerekir.
Uygulama, tüm görevlerin yürütmesi tamamlanmadan sonlanabilir. Örneğin, konsol uygulamaları içinde tüm zaman uyumlu kod
Main(uygulama giriş noktası) yürütülür yürütülmez sonlandırılır.
Aşağıdaki örnek, özel durum işleme içermeyen temel düzeni gösterir.
Task[] tasks = new Task[3]
{
Task.Factory.StartNew(() => MethodA()),
Task.Factory.StartNew(() => MethodB()),
Task.Factory.StartNew(() => MethodC())
};
//Block until all tasks complete.
Task.WaitAll(tasks);
// Continue on this thread...
Dim tasks() =
{
Task.Factory.StartNew(Sub() MethodA()),
Task.Factory.StartNew(Sub() MethodB()),
Task.Factory.StartNew(Sub() MethodC())
}
' Block until all tasks complete.
Task.WaitAll(tasks)
' Continue on this thread...
Özel durum işlemeyi gösteren bir örnek için bkz. Özel Durum İşleme.
Bazı aşırı yüklemeler bir zaman out(zaman) belirtmenize izin verir ve diğerleri giriş parametresi olarak ek bir değer alır; böylece beklemenin kendisi program aracılığıyla veya kullanıcı girişine yanıt CancellationToken olarak iptal edilir.
Bir görevi bekleseniz de, seçeneğini kullanarak bu görevin tüm küçüklerini örtülü olarak TaskCreationOptions.AttachedToParent beklersiniz. Task.Wait görev zaten tamamlandı ise hemen döndürür. Görev tamamlandıktan sonra yöntem çağrılsa bile, bir görev tarafından ortaya Task.Wait Task.Wait atılan özel durumlar bir yöntem tarafından atlanır.
Görevleri oluşturma
ve sınıfları, ortak desenleri uygulamak ve C#, Visual Basic ve F# tarafından sağlanan zaman uyumsuz dil özelliklerini daha iyi kullanmak için birden çok görev Task Task<TResult> oluşturmanıza yardımcı olan çeşitli yöntemler sağlar. Bu bölümde , WhenAll WhenAny , ve yöntemleri açık bir Delay şekilde FromResult anlattır.
Task.WhenAll
yöntemi, Task.WhenAll birden çok veya nesne için zaman uyumsuz olarak Task Task<TResult> tamamlar. Tek düzen olmayan görevler kümesini beklemenize olanak tanıyan aşırı yüklü sürümler sağlar. Örneğin, birden çok ve nesnelerinin bir Task Task<TResult> yöntem çağrısından tamamlanır.
Task.WhenAny
yöntemi, Task.WhenAny birden çok veya nesneden birinin Task bitip Task<TResult> bitimini zaman uyumsuz olarak bekler. yönteminde Task.WhenAll olduğu gibi bu yöntem de tekdüz olmayan görev kümelerini beklemeniz için aşırı yüklenmiş sürümler sağlar. yöntemi WhenAny özellikle aşağıdaki senaryolarda yararlıdır.
Yedekli işlemler. Birçok şekilde gerçekleştirilen bir algoritma veya işlem düşünün. önce tamamlanan WhenAny işlemi seçmek ve ardından kalan işlemleri iptal etmek için yöntemini kullanabilirsiniz.
Dönüşümlü işlemler. Hepsi bitip her işlem tamamlandı olarak sonuçları işleme WhenAny yöntemini kullanan birden çok işlem başlatebilirsiniz. Bir işlem tamamlandıktan sonra bir veya daha fazla ek görev başlatabilirsiniz.
Daraltılmış işlemler. Eşzamanlı işlem sayısını WhenAny sınırlaarak önceki senaryoyu genişletmek için yöntemini kullanabilirsiniz.
Süresi dolan işlemler. yöntemi tarafından döndürülen bir görev gibi bir veya daha fazla görev ile belirli bir süreden sonra sona ede bir görev arasında WhenAny seçim yapmak için yöntemini Delay kullanabilirsiniz. yöntemi Delay aşağıdaki bölümde açıklanmıştır.
Task.Delay
yöntemi, Task.Delay belirtilen Task sürenin ardından bitiren bir nesnesi üretir. Bazen verileri yoklayan, zaman aşımlarını tanıtan, belirli bir süre boyunca kullanıcı girişinin işlenmesini erteleyen, vb. işlemler yapan döngüler oluşturmak için bu yöntemi kullanabilirsiniz.
Task(T).FromResult
yöntemini Task.FromResult kullanarak önceden hesaplanan sonucu tutan bir nesne Task<TResult> oluşturabilirsiniz. Bu yöntem, bir nesnesi döndüren zaman uyumsuz bir işlem gerçekleştirecek ve bu Task<TResult> nesnenin sonucu Task<TResult> zaten hesaplandı olduğunda kullanışlıdır. Önbellekte düzenlenen zaman uyumsuz indirme işlemlerinin sonuçlarını almak için kullanan bir örnek FromResult için, bkz. How to: Create Pre-Computed Tasks.
Görevlerde özel durumları işleme
Bir görev bir veya daha fazla özel durum oluşturursa, özel durumlar bir özel durum içinde AggregateException sarmalar. Bu özel durum, genellikle görevin bitip bitimini bekleyen iş parçacığı veya özelliğine erişen iş parçacığı olan, görevle bire bir olan iş parçacığına Result geri yalıtıldı. Bu davranış, tüm işlenmemiş özel durumların varsayılan olarak işlemi sonlandırması gerektiğini belirten .NET Framework ilkesini zorlamaya yarar. Çağıran kod, bir blokta aşağıdakilerin herhangi birini kullanarak özel durumları try / catch işebilir:
Birleştirme iş parçacığı, görev atık toplamadan önce Exception özelliğine erişerek özel durumları da işebilir. Bu özelliğe erişerek, işlenmeyen özel durumun, nesne hazırlandığında işlemi sonlandıran özel durum yayma davranışını tetiklemesini engellersiniz.
Özel durumlar ve görevler hakkında daha fazla bilgi için bkz. Özel Durum İşleme.
Görevleri iptal etme
sınıfı, işbirliğine açık iptali destekler ve 4. yıl içinde tanıtılan ve sınıf Task System.Threading.CancellationTokenSource .NET Framework System.Threading.CancellationToken tümleştirilmiştir. sınıfındaki oluşturucuların çoğu System.Threading.Tasks.Task bir nesneyi giriş parametresi olarak CancellationToken alır. ve aşırı StartNew Run yüklemelerinin çoğu bir parametre CancellationToken de içerir.
belirteci oluşturabilir ve iptal isteğini daha sonra sınıfını kullanarak ve ardından veserinesi ile ve ardından ve ardından veserineyi kullanarak ve sonra da iptal isteğinde CancellationTokenSource bulundurabilirsiniz. Belirteci bağımsız değişken olarak değerine iletir ve aynı belirteci kullanıcı temsilcinize de (iptal isteğine Task yanıt verme çalışmasına) başvurur.
Daha fazla bilgi için, bkz. Görev İptali ve Nasıl: Bir Görevi İptal Etme ve Bunun Altında .
TaskFactory sınıfı
sınıfı, görevleri ve devamlılık görevlerini oluşturmaya ve başlatmaya için bazı ortak desenleri TaskFactory kapsülleyen statik yöntemler sağlar.
En yaygın desen, StartNew bir deyiminde görev oluşturan ve başlatan düzenidir.
Birden çok antecedent'den devamlılık görevleri oluşturduktan sonra, sınıfında yöntemini veya yöntemini veya ContinueWhenAll ContinueWhenAny eşdeğerlerini Task<TResult> kullanın. Daha fazla bilgi için bkz. Devamlılık Görevlerini Kullanarak Görevleri Zincirleme.
Bir veya örneğinde Zaman Uyumsuz Programlama Modeli ve
BeginXEndXyöntemleri Task kapsüllemek için yöntemlerini Task<TResult> FromAsync kullanın. Daha fazla bilgi için bkz. TPL ve Geleneksel .NET Framework Zaman Uyumsuz Programlama.
Varsayılan TaskFactory değere, sınıf veya sınıfta statik bir Task özellik olarak Task<TResult> erişilebilir. Ayrıca, doğrudan bir örneği ve bir , seçenek, seçenek veya TaskFactory CancellationToken içeren çeşitli seçenekler TaskCreationOptions TaskContinuationOptions TaskScheduler belirtebilirsiniz. Görev fabrikasını oluşturulduğunda belirtilen seçenekler, numaralama kullanılarak oluşturulmadıkça oluşturduğu tüm görevlere uygulanır; bu durumda görevin seçenekleri görev fabrikasının seçeneklerini Task TaskCreationOptions geçersiz kılar.
Temsilci olmayan görevler
Bazı durumlarda, kendi kullanıcı temsilciniz yerine bir dış bileşen tarafından gerçekleştirilen bazı zaman uyumsuz işlemi kapsüllemek için Task kullanabilirsiniz. İşlem Zaman Uyumsuz Programlama Modeli Başlangıç/Bitiş desenini temel aldısa, yöntemlerini FromAsync kullanabilirsiniz. Böyle bir durum yoksa, bir görev içinde işlemi sarmak için nesnesini kullanabilir ve böylece özel durum yayma ve devamlılık desteği gibi programlanabilirlik avantajlarından bazı avantajlar elde TaskCompletionSource<TResult> Task edersiniz. Daha fazla bilgi için bkz. TaskCompletionSource<TResult>.
Özel zamanlayıcılar
Çoğu uygulama veya kitaplık geliştiricisi görevin hangi işlemcide çalıştırlandığı, diğer görevlerle nasıl eşitlenmesi veya üzerinde nasıl zamanlandığıyla System.Threading.ThreadPool ilgilenmez. Bunlar yalnızca ana bilgisayarda olabildiğince verimli çalışmasını gerektirir. Zamanlama ayrıntıları üzerinde daha hassas bir denetim gerekiyorsa, Görev Paralel Kitaplığı varsayılan görev zamanlayıcı üzerinde bazı ayarları yapılandırmanıza ve hatta özel bir zamanlayıcı girmenize olanak tanır. Daha fazla bilgi için bkz. TaskScheduler.
İlgili veri yapıları
TPL'de, hem paralel hem de sıralı senaryolarda yararlı olan çeşitli, yeni genel türler vardır. Bunlar ad alanına birkaç iş parçacığı güvenli, hızlı ve ölçeklenebilir koleksiyon sınıfı ile belirli iş yükü türleri için öncüllerinden daha verimli olan ve gibi birkaç yeni eşitleme System.Collections.Concurrent System.Threading.Semaphore türü System.Threading.ManualResetEventSlim içerir. .NET Framework 4'te ve gibi diğer yeni System.Threading.Barrier System.Threading.SpinLock türler, önceki sürümlerde mevcut olan işlevleri sağlar. Daha fazla bilgi için bkz. Paralel Programlama için Veri Yapıları.
Özel görev türleri
veya 'den devralmamanizi System.Threading.Tasks.Task System.Threading.Tasks.Task<TResult> öneririz. Bunun yerine, ek verileri veya durumu AsyncState bir veya nesnesiyle ilişkilendirmek için özelliğini Task kullanmanizi Task<TResult> öneririz. Ve sınıflarının işlevselliğini genişletmek için uzantı yöntemlerini de Task Task<TResult> kullanabilirsiniz. Uzantı yöntemleri hakkında daha fazla bilgi için bkz. Uzantı Yöntemleri ve Uzantı Yöntemleri.
veya 'den devralmanız gerekirse, özel görev türü örnekleri oluşturmak için , veya , veya sınıflarını kullanılamaz çünkü bu mekanizmalar Task Task<TResult> yalnızca ve nesneleri Run System.Threading.Tasks.TaskFactory System.Threading.Tasks.TaskFactory<TResult> System.Threading.Tasks.TaskCompletionSource<TResult> Task Task<TResult> oluşturur. Ayrıca, özel görev türü örnekleri oluşturmak için , , ve tarafından sağlanan görev devamlılığı mekanizmalarını da kullanılamaz çünkü bu mekanizmalar yalnızca Task Task<TResult> ve nesneleri de TaskFactory TaskFactory<TResult> Task Task<TResult> oluşturur.
İlgili konular
| Başlık | Açıklama |
|---|---|
| Devamlılık Görevlerini Kullanarak Görevleri Birbirine Bağlama | Devamlılıkların nasıl çalıştığını açıklar. |
| Eklenen ve Ayrılan Alt Görevler | Ekli ve ayrılmış alt görevler arasındaki farkı açıklar. |
| Görev iptali | Nesnede yerleşik olarak yer alan iptal desteğini Task açıklar. |
| Özel Durum İşleme | Eşzamanlı iş parçacıklarındaki özel durumların nasıl işlendiğini açıklar. |
| Nasıl yapılır: Paralel İşlemleri Yürütmek için parallel_invoke Kullanma | kullanımını Invoke açıklar. |
| Nasıl yapılır: Bir Görevden Değer Döndürme | Değerlerin görevlerden nasıl döndürüleceğini açıklar. |
| Nasıl yapılır: Bir Görevi ve Alt Öğelerini İptal Etme | Görevlerin nasıl iptal edildiğini açıklar. |
| Nasıl yapılır: Önceden Hesaplanan Görevler Oluşturma | Bir önbellekte düzenlenen zaman uyumsuz indirme işlemlerinin sonuçlarını Task.FromResult almak için yönteminin nasıl kullanılası açıklandı. |
| Nasıl yapılır: Paralel Görevler İçeren Bir İkili Ağacı Gezme | İkili ağacı geçirmek için görevlerin nasıl kullanılacağını açıklar. |
| Nasıl yapılır: İç İçe Geçmiş Bir Görevi Sarmalamadan Çıkarma | Uzantı yönteminin nasıl Unwrap kullanıla bir şekilde gösterebilirsiniz. |
| Veri Paralelliği | Veriler üzerinde paralel For döngüler ForEach oluşturmak için ve kullanımını açıklar. |
| Paralel Programlama | .NET Framework paralel programlama için üst düzey düğüm. |