Kelas System.Threading.Tasks.Tasks
Artikel ini menyediakan keterangan tambahan untuk dokumentasi referensi untuk API ini.
Kelas Task mewakili satu operasi yang tidak mengembalikan nilai dan yang biasanya dijalankan secara asinkron. Task objek adalah salah satu komponen pusat dari pola asinkron berbasis tugas yang pertama kali diperkenalkan dalam .NET Framework 4. Karena pekerjaan yang Task dilakukan oleh objek biasanya dijalankan secara asinkron pada utas kumpulan utas daripada secara sinkron pada utas aplikasi utama, Anda dapat menggunakan Status properti, serta IsCanceledproperti , , IsCompleteddan IsFaulted , untuk menentukan status tugas. Paling umum, ekspresi lambda digunakan untuk menentukan pekerjaan yang akan dilakukan tugas.
Untuk operasi yang mengembalikan nilai, Anda menggunakan Task<TResult> kelas .
Instansiasi tugas
Contoh berikut membuat dan menjalankan empat tugas. Tiga tugas menjalankan Action<T> delegasi bernama action
, yang menerima argumen jenis Object. Tugas keempat menjalankan ekspresi lambda ( Action delegasi) yang didefinisikan sebaris dalam panggilan ke metode pembuatan tugas. Setiap tugas dibuat dan dijalankan dengan cara yang berbeda:
Tugas
t1
dibuat dengan memanggil konstruktor kelas Tugas, tetapi dimulai dengan memanggil metodenya Start() hanya setelah tugast2
dimulai.Tugas
t2
dibuat dan dimulai dalam satu panggilan metode dengan memanggil TaskFactory.StartNew(Action<Object>, Object) metode .Tugas
t3
dibuat dan dimulai dalam satu panggilan metode dengan memanggil Run(Action) metode .Tugas
t4
dijalankan secara sinkron pada utas utama dengan memanggil RunSynchronously() metode .
Karena tugas dijalankan secara sinkron, tugas t4
dijalankan pada utas aplikasi utama. Tugas yang tersisa dijalankan secara asinkron biasanya pada satu atau beberapa utas kumpulan utas.
using System;
using System.Threading;
using System.Threading.Tasks;
class Example1
{
static void Main()
{
Action<object> action = (object obj) =>
{
Console.WriteLine("Task={0}, obj={1}, Thread={2}",
Task.CurrentId, obj,
Thread.CurrentThread.ManagedThreadId);
};
// Create a task but do not start it.
Task t1 = new Task(action, "alpha");
// Construct a started task
Task t2 = Task.Factory.StartNew(action, "beta");
// Block the main thread to demonstrate that t2 is executing
t2.Wait();
// Launch t1
t1.Start();
Console.WriteLine("t1 has been launched. (Main Thread={0})",
Thread.CurrentThread.ManagedThreadId);
// Wait for the task to finish.
t1.Wait();
// Construct a started task using Task.Run.
String taskData = "delta";
Task t3 = Task.Run(() =>
{
Console.WriteLine("Task={0}, obj={1}, Thread={2}",
Task.CurrentId, taskData,
Thread.CurrentThread.ManagedThreadId);
});
// Wait for the task to finish.
t3.Wait();
// Construct an unstarted task
Task t4 = new Task(action, "gamma");
// Run it synchronously
t4.RunSynchronously();
// Although the task was run synchronously, it is a good practice
// to wait for it in the event exceptions were thrown by the task.
t4.Wait();
}
}
// The example displays output like the following:
// Task=1, obj=beta, Thread=3
// t1 has been launched. (Main Thread=1)
// Task=2, obj=alpha, Thread=4
// Task=3, obj=delta, Thread=3
// Task=4, obj=gamma, Thread=1
open System.Threading
open System.Threading.Tasks
let action =
fun (obj: obj) -> printfn $"Task={Task.CurrentId}, obj={obj}, Thread={Thread.CurrentThread.ManagedThreadId}"
// Create a task but do not start it.
let t1 = new Task(action, "alpha")
// Construct a started task
let t2 = Task.Factory.StartNew(action, "beta")
// Block the main thread to demonstrate that t2 is executing
t2.Wait()
// Launch t1
t1.Start()
printfn $"t1 has been launched. (Main Thread={Thread.CurrentThread.ManagedThreadId})"
// Wait for the task to finish.
t1.Wait()
// Construct a started task using Task.Run.
let taskData = "delta"
let t3 =
Task.Run(fun () -> printfn $"Task={Task.CurrentId}, obj={taskData}, Thread={Thread.CurrentThread.ManagedThreadId}")
// Wait for the task to finish.
t3.Wait()
// Construct an unstarted task
let t4 = new Task(action, "gamma")
// Run it synchronously
t4.RunSynchronously()
// Although the task was run synchronously, it is a good practice
// to wait for it in the event exceptions were thrown by the task.
t4.Wait()
// The example displays output like the following:
// Task=1, obj=beta, Thread=3
// t1 has been launched. (Main Thread=1)
// Task=2, obj=alpha, Thread=4
// Task=3, obj=delta, Thread=3
// Task=4, obj=gamma, Thread=1
Imports System.Threading
Imports System.Threading.Tasks
Module Example2
Public Sub Main()
Dim action As Action(Of Object) =
Sub(obj As Object)
Console.WriteLine("Task={0}, obj={1}, Thread={2}",
Task.CurrentId, obj,
Thread.CurrentThread.ManagedThreadId)
End Sub
' Construct an unstarted task
Dim t1 As New Task(action, "alpha")
' Construct a started task
Dim t2 As Task = Task.Factory.StartNew(action, "beta")
' Block the main thread to demonstrate that t2 is executing
t2.Wait()
' Launch t1
t1.Start()
Console.WriteLine("t1 has been launched. (Main Thread={0})",
Thread.CurrentThread.ManagedThreadId)
' Wait for the task to finish.
t1.Wait()
' Construct a started task using Task.Run.
Dim taskData As String = "delta"
Dim t3 As Task = Task.Run(Sub()
Console.WriteLine("Task={0}, obj={1}, Thread={2}",
Task.CurrentId, taskData,
Thread.CurrentThread.ManagedThreadId)
End Sub)
' Wait for the task to finish.
t3.Wait()
' Construct an unstarted task
Dim t4 As New Task(action, "gamma")
' Run it synchronously
t4.RunSynchronously()
' Although the task was run synchronously, it is a good practice
' to wait for it in the event exceptions were thrown by the task.
t4.Wait()
End Sub
End Module
' The example displays output like the following:
' Task=1, obj=beta, Thread=3
' t1 has been launched. (Main Thread=1)
' Task=2, obj=alpha, Thread=3
' Task=3, obj=delta, Thread=3
' Task=4, obj=gamma, Thread=1
Membuat dan menjalankan tugas
Anda dapat membuat Task instans dengan berbagai cara. Pendekatan yang paling umum adalah memanggil metode statis Run . Metode ini Run menyediakan cara sederhana untuk memulai tugas menggunakan nilai default dan tanpa memerlukan parameter tambahan. Contoh berikut menggunakan Run(Action) metode untuk memulai tugas yang mengulang lalu menampilkan jumlah perulangan perulangan:
using System;
using System.Threading.Tasks;
public class Example
{
public static async Task Main()
{
await Task.Run( () => {
// Just loop.
int ctr = 0;
for (ctr = 0; ctr <= 1000000; ctr++)
{}
Console.WriteLine("Finished {0} loop iterations",
ctr);
} );
}
}
// The example displays the following output:
// Finished 1000001 loop iterations
open System.Threading.Tasks
let main =
task {
do!
Task.Run(fun () ->
for i = 0 to 1000000 do
printfn $"Finished {i} loop iterations")
}
main.Wait()
// The example displays the following output:
// Finished 1000001 loop iterations
Imports System.Threading.Tasks
Module Example1
Public Sub Main()
Dim t As Task = Task.Run(Sub()
' Just loop.
Dim ctr As Integer = 0
For ctr = 0 To 1000000
Next
Console.WriteLine("Finished {0} loop iterations",
ctr)
End Sub)
t.Wait()
End Sub
End Module
' The example displays the following output:
' Finished 1000001 loop iterations
Alternatifnya adalah metode statis TaskFactory.StartNew . Properti Task.Factory mengembalikan TaskFactory objek. Kelebihan beban TaskFactory.StartNew metode memungkinkan Anda menentukan parameter untuk diteruskan ke opsi pembuatan tugas dan penjadwal tugas. Contoh berikut menggunakan TaskFactory.StartNew metode untuk memulai tugas. Ini secara fungsional setara dengan kode dalam contoh sebelumnya.
using System;
using System.Threading.Tasks;
public class Example2
{
public static void Main()
{
Task t = Task.Factory.StartNew(() =>
{
// Just loop.
int ctr = 0;
for (ctr = 0; ctr <= 1000000; ctr++)
{ }
Console.WriteLine("Finished {0} loop iterations",
ctr);
});
t.Wait();
}
}
// The example displays the following output:
// Finished 1000001 loop iterations
open System.Threading.Tasks
let t =
Task.Factory.StartNew(fun () ->
// Just loop.
for i = 0 to 1000000 do
printfn $"Finished {i} loop iterations")
t.Wait()
// The example displays the following output:
// Finished 1000001 loop iterations
Imports System.Threading.Tasks
Module Example3
Public Sub Main()
Dim t As Task = Task.Factory.StartNew(Sub()
' Just loop.
Dim ctr As Integer = 0
For ctr = 0 To 1000000
Next
Console.WriteLine("Finished {0} loop iterations",
ctr)
End Sub)
t.Wait()
End Sub
End Module
' The example displays the following output:
' Finished 1000001 loop iterations
Untuk contoh yang lebih lengkap, lihat Pemrograman Asinkron berbasis tugas.
Memisahkan pembuatan dan eksekusi tugas
Kelas ini Task juga menyediakan konstruktor yang menginisialisasi tugas tetapi tidak menjadwalkannya untuk eksekusi. Untuk alasan performa, Task.Run metode atau TaskFactory.StartNew adalah mekanisme yang disukai untuk membuat dan menjadwalkan tugas komputasi, tetapi untuk skenario di mana pembuatan dan penjadwalan harus dipisahkan, Anda dapat menggunakan konstruktor dan kemudian memanggil metode untuk menjadwalkan Task.Start tugas untuk dieksekusi di lain waktu.
Tunggu tugas selesai
Karena tugas biasanya berjalan secara asinkron pada utas kumpulan utas, alur yang membuat dan memulai tugas melanjutkan eksekusi segera setelah tugas dibuat. Dalam beberapa kasus, ketika utas panggilan adalah utas aplikasi utama, aplikasi dapat dihentikan sebelum tugas benar-benar memulai eksekusi. Di yang lain, logika aplikasi Anda mungkin mengharuskan utas panggilan melanjutkan eksekusi hanya ketika satu atau beberapa tugas telah menyelesaikan eksekusi. Anda dapat menyinkronkan eksekusi utas panggilan dan tugas asinkron yang diluncurkannya dengan memanggil Wait
metode untuk menunggu satu atau beberapa tugas selesai.
Untuk menunggu satu tugas selesai, Anda dapat memanggil metodenya Task.Wait . Panggilan ke Wait metode memblokir utas panggilan hingga instans kelas tunggal selesai dieksekusi.
Contoh berikut memanggil metode tanpa Wait() parameter untuk menunggu tanpa syarat hingga tugas selesai. Tugas mensimulasikan pekerjaan dengan memanggil Thread.Sleep metode untuk tidur selama dua detik.
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static Random rand = new Random();
static void Main()
{
// Wait on a single task with no timeout specified.
Task taskA = Task.Run( () => Thread.Sleep(2000));
Console.WriteLine("taskA Status: {0}", taskA.Status);
try {
taskA.Wait();
Console.WriteLine("taskA Status: {0}", taskA.Status);
}
catch (AggregateException) {
Console.WriteLine("Exception in taskA.");
}
}
}
// The example displays output like the following:
// taskA Status: WaitingToRun
// taskA Status: RanToCompletion
open System
open System.Threading
open System.Threading.Tasks
let rand = Random()
// Wait on a single task with no timeout specified.
let taskA = Task.Run(fun () -> Thread.Sleep 2000)
printfn $"taskA Status: {taskA.Status}"
try
taskA.Wait()
printfn $"taskA Status: {taskA.Status}"
with :? AggregateException ->
printfn "Exception in taskA."
// The example displays output like the following:
// taskA Status: WaitingToRun
// taskA Status: RanToCompletion
Imports System.Threading
Imports System.Threading.Tasks
Module Example4
Public Sub Main()
' Wait on a single task with no timeout specified.
Dim taskA = Task.Run(Sub() Thread.Sleep(2000))
Console.WriteLine("taskA Status: {0}", taskA.Status)
Try
taskA.Wait()
Console.WriteLine("taskA Status: {0}", taskA.Status)
Catch e As AggregateException
Console.WriteLine("Exception in taskA.")
End Try
End Sub
End Module
' The example displays output like the following:
' taskA Status: WaitingToRun
' taskA Status: RanToCompletion
Anda juga dapat secara kondisional menunggu tugas selesai. Metode Wait(Int32) dan Wait(TimeSpan) memblokir utas panggilan sampai tugas selesai atau interval batas waktu berlalu, mana yang lebih dulu. Karena contoh berikut meluncurkan tugas yang tidur selama dua detik tetapi menentukan nilai batas waktu satu detik, utas panggilan memblokir hingga batas waktu berakhir dan sebelum tugas selesai dieksekusi.
using System;
using System.Threading;
using System.Threading.Tasks;
public class Example5
{
public static void Main()
{
// Wait on a single task with a timeout specified.
Task taskA = Task.Run(() => Thread.Sleep(2000));
try
{
taskA.Wait(1000); // Wait for 1 second.
bool completed = taskA.IsCompleted;
Console.WriteLine("Task A completed: {0}, Status: {1}",
completed, taskA.Status);
if (!completed)
Console.WriteLine("Timed out before task A completed.");
}
catch (AggregateException)
{
Console.WriteLine("Exception in taskA.");
}
}
}
// The example displays output like the following:
// Task A completed: False, Status: Running
// Timed out before task A completed.
open System
open System.Threading
open System.Threading.Tasks
// Wait on a single task with a timeout specified.
let taskA = Task.Run(fun () -> Thread.Sleep 2000)
try
taskA.Wait 1000 |> ignore // Wait for 1 second.
let completed = taskA.IsCompleted
printfn $"Task A completed: {completed}, Status: {taskA.Status}"
if not completed then
printfn "Timed out before task A completed."
with :? AggregateException ->
printfn "Exception in taskA."
// The example displays output like the following:
// Task A completed: False, Status: Running
// Timed out before task A completed.
Imports System.Threading
Imports System.Threading.Tasks
Module Example5
Public Sub Main()
' Wait on a single task with a timeout specified.
Dim taskA As Task = Task.Run(Sub() Thread.Sleep(2000))
Try
taskA.Wait(1000) ' Wait for 1 second.
Dim completed As Boolean = taskA.IsCompleted
Console.WriteLine("Task.Completed: {0}, Status: {1}",
completed, taskA.Status)
If Not completed Then
Console.WriteLine("Timed out before task A completed.")
End If
Catch e As AggregateException
Console.WriteLine("Exception in taskA.")
End Try
End Sub
End Module
' The example displays the following output:
' Task A completed: False, Status: Running
' Timed out before task A completed.
Anda juga dapat menyediakan token pembatalan dengan memanggil Wait(CancellationToken) metode dan Wait(Int32, CancellationToken) . Jika properti token IsCancellationRequested adalah true
atau menjadi true
saat Wait metode dijalankan, metode akan melemparkan OperationCanceledException.
Dalam beberapa kasus, Anda mungkin ingin menunggu serangkaian tugas eksekusi pertama selesai, tetapi tidak peduli tugas mana itu. Untuk tujuan ini, Anda dapat memanggil salah satu kelebihan beban Task.WaitAny metode. Contoh berikut membuat tiga tugas, yang masing-masing tidur untuk interval yang ditentukan oleh generator angka acak. Metode WaitAny(Task[]) menunggu tugas pertama selesai. Contoh kemudian menampilkan informasi tentang status ketiga tugas.
using System;
using System.Threading;
using System.Threading.Tasks;
public class Example4
{
public static void Main()
{
var tasks = new Task[3];
var rnd = new Random();
for (int ctr = 0; ctr <= 2; ctr++)
tasks[ctr] = Task.Run(() => Thread.Sleep(rnd.Next(500, 3000)));
try
{
int index = Task.WaitAny(tasks);
Console.WriteLine("Task #{0} completed first.\n", tasks[index].Id);
Console.WriteLine("Status of all tasks:");
foreach (var t in tasks)
Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status);
}
catch (AggregateException)
{
Console.WriteLine("An exception occurred.");
}
}
}
// The example displays output like the following:
// Task #1 completed first.
//
// Status of all tasks:
// Task #3: Running
// Task #1: RanToCompletion
// Task #4: Running
open System
open System.Threading
open System.Threading.Tasks
let rnd = new Random()
let tasks =
[| for _ = 0 to 2 do
Task.Run(fun () -> rnd.Next(500, 3000) |> Thread.Sleep) |]
try
let index = Task.WaitAny tasks
printfn $"Task #{tasks[index].Id} completed first.\n"
printfn "Status of all tasks:"
for t in tasks do
printfn $" Task #{t.Id}: {t.Status}"
with :? AggregateException ->
printfn "An exception occurred."
// The example displays output like the following:
// Task #1 completed first.
//
// Status of all tasks:
// Task #3: Running
// Task #1: RanToCompletion
// Task #4: Running
Imports System.Threading
Module Example8
Public Sub Main()
Dim tasks(2) As Task
Dim rnd As New Random()
For ctr As Integer = 0 To 2
tasks(ctr) = Task.Run(Sub() Thread.Sleep(rnd.Next(500, 3000)))
Next
Try
Dim index As Integer = Task.WaitAny(tasks)
Console.WriteLine("Task #{0} completed first.", tasks(index).Id)
Console.WriteLine()
Console.WriteLine("Status of all tasks:")
For Each t In tasks
Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status)
Next
Catch e As AggregateException
Console.WriteLine("An exception occurred.")
End Try
End Sub
End Module
' The example displays output like the following:
' Task #1 completed first.
'
' Status of all tasks:
' Task #3: Running
' Task #1: RanToCompletion
' Task #4: Running
Anda juga dapat menunggu semua rangkaian tugas selesai dengan memanggil WaitAll metode . Contoh berikut membuat sepuluh tugas, menunggu kesepuluh tugas selesai, lalu menampilkan statusnya.
using System;
using System.Threading;
using System.Threading.Tasks;
public class Example3
{
public static void Main()
{
// Wait for all tasks to complete.
Task[] tasks = new Task[10];
for (int i = 0; i < 10; i++)
{
tasks[i] = Task.Run(() => Thread.Sleep(2000));
}
try
{
Task.WaitAll(tasks);
}
catch (AggregateException ae)
{
Console.WriteLine("One or more exceptions occurred: ");
foreach (var ex in ae.Flatten().InnerExceptions)
Console.WriteLine(" {0}", ex.Message);
}
Console.WriteLine("Status of completed tasks:");
foreach (var t in tasks)
Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status);
}
}
// The example displays the following output:
// Status of completed tasks:
// Task #2: RanToCompletion
// Task #1: RanToCompletion
// Task #3: RanToCompletion
// Task #4: RanToCompletion
// Task #6: RanToCompletion
// Task #5: RanToCompletion
// Task #7: RanToCompletion
// Task #8: RanToCompletion
// Task #9: RanToCompletion
// Task #10: RanToCompletion
open System
open System.Threading
open System.Threading.Tasks
// Wait for all tasks to complete.
let tasks =
[| for _ = 0 to 9 do
Task.Run(fun () -> Thread.Sleep 2000) |]
try
Task.WaitAll tasks
with :? AggregateException as ae ->
printfn "One or more exceptions occurred: "
for ex in ae.Flatten().InnerExceptions do
printfn $" {ex.Message}"
printfn "Status of completed tasks:"
for t in tasks do
printfn $" Task #{t.Id}: {t.Status}"
// The example displays the following output:
// Status of completed tasks:
// Task #2: RanToCompletion
// Task #1: RanToCompletion
// Task #3: RanToCompletion
// Task #4: RanToCompletion
// Task #6: RanToCompletion
// Task #5: RanToCompletion
// Task #7: RanToCompletion
// Task #8: RanToCompletion
// Task #9: RanToCompletion
// Task #10: RanToCompletion
Imports System.Threading
Imports System.Threading.Tasks
Module Example6
Public Sub Main()
' Wait for all tasks to complete.
Dim tasks(9) As Task
For i As Integer = 0 To 9
tasks(i) = Task.Run(Sub() Thread.Sleep(2000))
Next
Try
Task.WaitAll(tasks)
Catch ae As AggregateException
Console.WriteLine("One or more exceptions occurred: ")
For Each ex In ae.Flatten().InnerExceptions
Console.WriteLine(" {0}", ex.Message)
Next
End Try
Console.WriteLine("Status of completed tasks:")
For Each t In tasks
Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status)
Next
End Sub
End Module
' The example displays the following output:
' Status of completed tasks:
' Task #2: RanToCompletion
' Task #1: RanToCompletion
' Task #3: RanToCompletion
' Task #4: RanToCompletion
' Task #6: RanToCompletion
' Task #5: RanToCompletion
' Task #7: RanToCompletion
' Task #8: RanToCompletion
' Task #9: RanToCompletion
' Task #10: RanToCompletion
Perhatikan bahwa ketika Anda menunggu satu atau beberapa tugas selesai, pengecualian apa pun yang dilemparkan dalam tugas yang sedang berjalan disebarkan pada utas Wait
yang memanggil metode , seperti yang ditunjukkan contoh berikut. Ini meluncurkan 12 tugas, tiga di antaranya selesai secara normal dan tiga di antaranya melemparkan pengecualian. Dari enam tugas yang tersisa, tiga dibatalkan sebelum dimulai, dan tiga dibatalkan saat sedang dieksekusi. Pengecualian dilemparkan WaitAll dalam panggilan metode dan ditangani oleh try
/catch
blok.
using System;
using System.Threading;
using System.Threading.Tasks;
public class Example6
{
public static void Main()
{
// Create a cancellation token and cancel it.
var source1 = new CancellationTokenSource();
var token1 = source1.Token;
source1.Cancel();
// Create a cancellation token for later cancellation.
var source2 = new CancellationTokenSource();
var token2 = source2.Token;
// Create a series of tasks that will complete, be cancelled,
// timeout, or throw an exception.
Task[] tasks = new Task[12];
for (int i = 0; i < 12; i++)
{
switch (i % 4)
{
// Task should run to completion.
case 0:
tasks[i] = Task.Run(() => Thread.Sleep(2000));
break;
// Task should be set to canceled state.
case 1:
tasks[i] = Task.Run(() => Thread.Sleep(2000),
token1);
break;
case 2:
// Task should throw an exception.
tasks[i] = Task.Run(() => { throw new NotSupportedException(); });
break;
case 3:
// Task should examine cancellation token.
tasks[i] = Task.Run(() =>
{
Thread.Sleep(2000);
if (token2.IsCancellationRequested)
token2.ThrowIfCancellationRequested();
Thread.Sleep(500);
}, token2);
break;
}
}
Thread.Sleep(250);
source2.Cancel();
try
{
Task.WaitAll(tasks);
}
catch (AggregateException ae)
{
Console.WriteLine("One or more exceptions occurred:");
foreach (var ex in ae.InnerExceptions)
Console.WriteLine(" {0}: {1}", ex.GetType().Name, ex.Message);
}
Console.WriteLine("\nStatus of tasks:");
foreach (var t in tasks)
{
Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status);
if (t.Exception != null)
{
foreach (var ex in t.Exception.InnerExceptions)
Console.WriteLine(" {0}: {1}", ex.GetType().Name,
ex.Message);
}
}
}
}
// The example displays output like the following:
// One or more exceptions occurred:
// TaskCanceledException: A task was canceled.
// NotSupportedException: Specified method is not supported.
// TaskCanceledException: A task was canceled.
// TaskCanceledException: A task was canceled.
// NotSupportedException: Specified method is not supported.
// TaskCanceledException: A task was canceled.
// TaskCanceledException: A task was canceled.
// NotSupportedException: Specified method is not supported.
// TaskCanceledException: A task was canceled.
//
// Status of tasks:
// Task #13: RanToCompletion
// Task #1: Canceled
// Task #3: Faulted
// NotSupportedException: Specified method is not supported.
// Task #8: Canceled
// Task #14: RanToCompletion
// Task #4: Canceled
// Task #6: Faulted
// NotSupportedException: Specified method is not supported.
// Task #7: Canceled
// Task #15: RanToCompletion
// Task #9: Canceled
// Task #11: Faulted
// NotSupportedException: Specified method is not supported.
// Task #12: Canceled
open System
open System.Threading
open System.Threading.Tasks
// Create a cancellation token and cancel it.
let source1 = new CancellationTokenSource()
let token1 = source1.Token
source1.Cancel()
// Create a cancellation token for later cancellation.
let source2 = new CancellationTokenSource()
let token2 = source2.Token
// Create a series of tasks that will complete, be cancelled,
// timeout, or throw an exception.
let tasks =
[| for i in 0..11 do
match i % 4 with
// Task should run to completion.
| 0 -> Task.Run(fun () -> Thread.Sleep 2000)
// Task should be set to canceled state.
| 1 -> Task.Run(fun () -> Thread.Sleep 2000, token1)
// Task should throw an exception.
| 2 -> Task.Run(fun () -> NotSupportedException())
// Task should examine cancellation token.
| _ ->
Task.Run(fun () ->
Thread.Sleep 2000
if token2.IsCancellationRequested then
token2.ThrowIfCancellationRequested()
Thread.Sleep 500, token2) |]
Thread.Sleep 250
source2.Cancel()
try
Task.WaitAll tasks
with :? AggregateException as ae ->
printfn "One or more exceptions occurred:"
for ex in ae.InnerExceptions do
printfn $" {ex.GetType().Name}: {ex.Message}"
printfn "\nStatus of tasks:"
for t in tasks do
printfn $" Task #{t.Id}: {t.Status}"
if isNull t.Exception |> not then
for ex in t.Exception.InnerExceptions do
printfn $" {ex.GetType().Name}: {ex.Message}"
// The example displays output like the following:
// One or more exceptions occurred:
// TaskCanceledException: A task was canceled.
// NotSupportedException: Specified method is not supported.
// TaskCanceledException: A task was canceled.
// TaskCanceledException: A task was canceled.
// NotSupportedException: Specified method is not supported.
// TaskCanceledException: A task was canceled.
// TaskCanceledException: A task was canceled.
// NotSupportedException: Specified method is not supported.
// TaskCanceledException: A task was canceled.
//
// Status of tasks:
// Task #13: RanToCompletion
// Task #1: Canceled
// Task #3: Faulted
// NotSupportedException: Specified method is not supported.
// Task #8: Canceled
// Task #14: RanToCompletion
// Task #4: Canceled
// Task #6: Faulted
// NotSupportedException: Specified method is not supported.
// Task #7: Canceled
// Task #15: RanToCompletion
// Task #9: Canceled
// Task #11: Faulted
// NotSupportedException: Specified method is not supported.
// Task #12: Canceled
Imports System.Threading
Imports System.Threading.Tasks
Module Example7
Public Sub Main()
' Create a cancellation token and cancel it.
Dim source1 As New CancellationTokenSource()
Dim token1 As CancellationToken = source1.Token
source1.Cancel()
' Create a cancellation token for later cancellation.
Dim source2 As New CancellationTokenSource()
Dim token2 As CancellationToken = source2.Token
' Create a series of tasks that will complete, be cancelled,
' timeout, or throw an exception.
Dim tasks(11) As Task
For i As Integer = 0 To 11
Select Case i Mod 4
' Task should run to completion.
Case 0
tasks(i) = Task.Run(Sub() Thread.Sleep(2000))
' Task should be set to canceled state.
Case 1
tasks(i) = Task.Run(Sub() Thread.Sleep(2000), token1)
Case 2
' Task should throw an exception.
tasks(i) = Task.Run(Sub()
Throw New NotSupportedException()
End Sub)
Case 3
' Task should examine cancellation token.
tasks(i) = Task.Run(Sub()
Thread.Sleep(2000)
If token2.IsCancellationRequested Then
token2.ThrowIfCancellationRequested()
End If
Thread.Sleep(500)
End Sub, token2)
End Select
Next
Thread.Sleep(250)
source2.Cancel()
Try
Task.WaitAll(tasks)
Catch ae As AggregateException
Console.WriteLine("One or more exceptions occurred:")
For Each ex In ae.InnerExceptions
Console.WriteLine(" {0}: {1}", ex.GetType().Name, ex.Message)
Next
End Try
Console.WriteLine()
Console.WriteLine("Status of tasks:")
For Each t In tasks
Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status)
If t.Exception IsNot Nothing Then
For Each ex In t.Exception.InnerExceptions
Console.WriteLine(" {0}: {1}", ex.GetType().Name,
ex.Message)
Next
End If
Next
End Sub
End Module
' The example displays output like the following:
' One or more exceptions occurred:
' TaskCanceledException: A task was canceled.
' NotSupportedException: Specified method is not supported.
' TaskCanceledException: A task was canceled.
' TaskCanceledException: A task was canceled.
' NotSupportedException: Specified method is not supported.
' TaskCanceledException: A task was canceled.
' TaskCanceledException: A task was canceled.
' NotSupportedException: Specified method is not supported.
' TaskCanceledException: A task was canceled.
'
' Status of tasks:
' Task #13: RanToCompletion
' Task #1: Canceled
' Task #3: Faulted
' NotSupportedException: Specified method is not supported.
' Task #8: Canceled
' Task #14: RanToCompletion
' Task #4: Canceled
' Task #6: Faulted
' NotSupportedException: Specified method is not supported.
' Task #7: Canceled
' Task #15: RanToCompletion
' Task #9: Canceled
' Task #11: Faulted
' NotSupportedException: Specified method is not supported.
' Task #12: Canceled
Untuk informasi selengkapnya tentang penanganan pengecualian dalam operasi asinkron berbasis tugas, lihat Penanganan Pengecualian.
Tugas dan budaya
Dimulai dengan aplikasi desktop yang menargetkan .NET Framework 4.6, budaya utas yang membuat dan memanggil tugas menjadi bagian dari konteks utas. Artinya, terlepas dari budaya utas saat ini di mana tugas dijalankan, budaya tugas saat ini adalah budaya utas panggilan. Untuk aplikasi yang menargetkan versi .NET Framework sebelum .NET Framework 4.6, budaya tugas adalah budaya utas tempat tugas dijalankan. Untuk informasi selengkapnya, lihat bagian "Budaya dan operasi asinkron berbasis tugas" dalam topik.CultureInfo
Catatan
Aplikasi store mengikuti Windows Runtime dalam pengaturan dan mendapatkan budaya default.
Untuk pengembang debugger
Untuk pengembang yang menerapkan debugger kustom, beberapa anggota internal dan privat tugas mungkin berguna (ini dapat berubah dari rilis ke rilis). Bidang berfungsi m_taskId
sebagai penyimpanan cadangan untuk Id properti, namun mengakses bidang ini langsung dari debugger mungkin lebih efisien daripada mengakses nilai yang sama melalui metode getter properti ( s_taskIdCounter
penghitung digunakan untuk mengambil ID berikutnya yang tersedia untuk tugas). Demikian pula, m_stateFlags
bidang menyimpan informasi tentang tahap siklus hidup tugas saat ini, informasi juga dapat diakses melalui Status properti . Bidang m_action
menyimpan referensi ke delegasi tugas, dan m_stateObject
bidang menyimpan status asinkron yang diteruskan ke tugas oleh pengembang. Terakhir, untuk debugger yang mengurai bingkai tumpukan, InternalWait
metode ini melayani penanda potensial ketika tugas memasuki operasi tunggu.
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk