6
6
7
7
public class Example
8
8
{
9
- public static void Main ( )
10
- {
11
- var tokenSource = new CancellationTokenSource ( ) ;
12
- var token = tokenSource . Token ;
9
+ public static async Task Main ( )
10
+ {
11
+ var tokenSource = new CancellationTokenSource ( ) ;
12
+ var token = tokenSource . Token ;
13
13
14
- // Store references to the tasks so that we can wait on them and
15
- // observe their status after cancellation.
16
- Task t ;
17
- var tasks = new ConcurrentBag < Task > ( ) ;
14
+ // Store references to the tasks so that we can wait on them and
15
+ // observe their status after cancellation.
16
+ Task t ;
17
+ var tasks = new ConcurrentBag < Task > ( ) ;
18
18
19
- Console . WriteLine ( "Press any key to begin tasks..." ) ;
20
- Console . ReadKey ( true ) ;
21
- Console . WriteLine ( "To terminate the example, press 'c' to cancel and exit..." ) ;
22
- Console . WriteLine ( ) ;
23
-
24
- // Request cancellation of a single task when the token source is canceled.
25
- // Pass the token to the user delegate, and also to the task so it can
26
- // handle the exception correctly.
27
- t = Task . Factory . StartNew ( ( ) => DoSomeWork ( 1 , token ) , token ) ;
28
- Console . WriteLine ( "Task {0} executing" , t . Id ) ;
29
- tasks . Add ( t ) ;
19
+ Console . WriteLine ( "Press any key to begin tasks..." ) ;
20
+ Console . ReadKey ( true ) ;
21
+ Console . WriteLine ( "To terminate the example, press 'c' to cancel and exit..." ) ;
22
+ Console . WriteLine ( ) ;
23
+
24
+ // Request cancellation of a single task when the token source is canceled.
25
+ // Pass the token to the user delegate, and also to the task so it can
26
+ // handle the exception correctly.
27
+ t = Task . Run ( ( ) => DoSomeWork ( 1 , token ) , token ) ;
28
+ Console . WriteLine ( "Task {0} executing" , t . Id ) ;
29
+ tasks . Add ( t ) ;
30
+
31
+ // Request cancellation of a task and its children. Note the token is passed
32
+ // to (1) the user delegate and (2) as the second argument to Task.Run, so
33
+ // that the task instance can correctly handle the OperationCanceledException.
34
+ t = Task . Run ( ( ) =>
35
+ {
36
+ // Create some cancelable child tasks.
37
+ Task tc ;
38
+ for ( int i = 3 ; i <= 10 ; i ++ )
39
+ {
40
+ // For each child task, pass the same token
41
+ // to each user delegate and to Task.Run.
42
+ tc = Task . Run ( ( ) => DoSomeWork ( i , token ) , token ) ;
43
+ Console . WriteLine ( "Task {0} executing" , tc . Id ) ;
44
+ tasks . Add ( tc ) ;
45
+ // Pass the same token again to do work on the parent task.
46
+ // All will be signaled by the call to tokenSource.Cancel below.
47
+ DoSomeWork ( 2 , token ) ;
48
+ }
49
+ } , token ) ;
30
50
31
- // Request cancellation of a task and its children. Note the token is passed
32
- // to (1) the user delegate and (2) as the second argument to StartNew, so
33
- // that the task instance can correctly handle the OperationCanceledException.
34
- t = Task . Factory . StartNew ( ( ) => {
35
- // Create some cancelable child tasks.
36
- Task tc ;
37
- for ( int i = 3 ; i <= 10 ; i ++ ) {
38
- // For each child task, pass the same token
39
- // to each user delegate and to StartNew.
40
- tc = Task . Factory . StartNew ( iteration => DoSomeWork ( ( int ) iteration , token ) , i , token ) ;
41
- Console . WriteLine ( "Task {0} executing" , tc . Id ) ;
42
- tasks . Add ( tc ) ;
43
- // Pass the same token again to do work on the parent task.
44
- // All will be signaled by the call to tokenSource.Cancel below.
45
- DoSomeWork ( 2 , token ) ;
46
- }
47
- } ,
48
- token ) ;
49
-
50
51
Console . WriteLine ( "Task {0} executing" , t . Id ) ;
51
52
tasks . Add ( t ) ;
52
53
53
54
// Request cancellation from the UI thread.
54
55
char ch = Console . ReadKey ( ) . KeyChar ;
55
- if ( ch == 'c' || ch == 'C' ) {
56
+ if ( ch == 'c' || ch == 'C' )
57
+ {
56
58
tokenSource . Cancel ( ) ;
57
59
Console . WriteLine ( "\n Task cancellation requested." ) ;
58
60
@@ -61,63 +63,59 @@ public static void Main()
61
63
// if you do wait, you must enclose the call in a try-catch block to
62
64
// catch the TaskCanceledExceptions that are thrown. If you do
63
65
// not wait, no exception is thrown if the token that was passed to the
64
- // StartNew method is the same token that requested the cancellation.
65
- }
66
+ // Task.Run method is the same token that requested the cancellation.
67
+ }
66
68
67
- try {
68
- Task . WaitAll ( tasks . ToArray ( ) ) ;
69
+ try
70
+ {
71
+ await Task . WhenAll ( tasks . ToArray ( ) ) ;
69
72
}
70
- catch ( AggregateException e ) {
71
- Console . WriteLine ( "\n AggregateException thrown with the following inner exceptions:" ) ;
72
- // Display information about each exception.
73
- foreach ( var v in e . InnerExceptions ) {
74
- if ( v is TaskCanceledException )
75
- Console . WriteLine ( " TaskCanceledException: Task {0}" ,
76
- ( ( TaskCanceledException ) v ) . Task . Id ) ;
77
- else
78
- Console . WriteLine ( " Exception: {0}" , v . GetType ( ) . Name ) ;
79
- }
80
- Console . WriteLine ( ) ;
73
+ catch ( OperationCanceledException )
74
+ {
75
+ Console . WriteLine ( $ "\n { nameof ( OperationCanceledException ) } thrown\n ") ;
81
76
}
82
77
finally
83
78
{
84
- tokenSource . Dispose ( ) ;
79
+ tokenSource . Dispose ( ) ;
85
80
}
86
81
87
82
// Display status of all tasks.
88
83
foreach ( var task in tasks )
89
84
Console . WriteLine ( "Task {0} status is now {1}" , task . Id , task . Status ) ;
90
- }
85
+ }
91
86
92
- static void DoSomeWork ( int taskNum , CancellationToken ct )
93
- {
94
- // Was cancellation already requested?
95
- if ( ct . IsCancellationRequested == true ) {
96
- Console . WriteLine ( "Task {0} was cancelled before it got started." ,
97
- taskNum ) ;
98
- ct . ThrowIfCancellationRequested ( ) ;
99
- }
87
+ static void DoSomeWork ( int taskNum , CancellationToken ct )
88
+ {
89
+ // Was cancellation already requested?
90
+ if ( ct . IsCancellationRequested )
91
+ {
92
+ Console . WriteLine ( "Task {0} was cancelled before it got started." ,
93
+ taskNum ) ;
94
+ ct . ThrowIfCancellationRequested ( ) ;
95
+ }
100
96
101
- int maxIterations = 100 ;
97
+ int maxIterations = 100 ;
102
98
103
- // NOTE!!! A "TaskCanceledException was unhandled
104
- // by user code" error will be raised here if "Just My Code"
105
- // is enabled on your computer. On Express editions JMC is
106
- // enabled and cannot be disabled. The exception is benign.
107
- // Just press F5 to continue executing your code.
108
- for ( int i = 0 ; i <= maxIterations ; i ++ ) {
109
- // Do a bit of work. Not too much.
110
- var sw = new SpinWait ( ) ;
111
- for ( int j = 0 ; j <= 100 ; j ++ )
112
- sw . SpinOnce ( ) ;
99
+ // NOTE!!! A "TaskCanceledException was unhandled
100
+ // by user code" error will be raised here if "Just My Code"
101
+ // is enabled on your computer. On Express editions JMC is
102
+ // enabled and cannot be disabled. The exception is benign.
103
+ // Just press F5 to continue executing your code.
104
+ for ( int i = 0 ; i <= maxIterations ; i ++ )
105
+ {
106
+ // Do a bit of work. Not too much.
107
+ var sw = new SpinWait ( ) ;
108
+ for ( int j = 0 ; j <= 100 ; j ++ )
109
+ sw . SpinOnce ( ) ;
113
110
114
- if ( ct . IsCancellationRequested ) {
115
- Console . WriteLine ( "Task {0} cancelled" , taskNum ) ;
116
- ct . ThrowIfCancellationRequested ( ) ;
117
- }
118
- }
119
- }
120
- }
111
+ if ( ct . IsCancellationRequested )
112
+ {
113
+ Console . WriteLine ( "Task {0} cancelled" , taskNum ) ;
114
+ ct . ThrowIfCancellationRequested ( ) ;
115
+ }
116
+ }
117
+ }
118
+ }
121
119
// The example displays output like the following:
122
120
// Press any key to begin tasks...
123
121
// To terminate the example, press 'c' to cancel and exit...
@@ -135,10 +133,7 @@ static void DoSomeWork(int taskNum, CancellationToken ct)
135
133
// Task 2 cancelled
136
134
// Task 7 cancelled
137
135
//
138
- // AggregateException thrown with the following inner exceptions:
139
- // TaskCanceledException: Task 2
140
- // TaskCanceledException: Task 8
141
- // TaskCanceledException: Task 7
136
+ // OperationCanceledException thrown
142
137
//
143
138
// Task 2 status is now Canceled
144
139
// Task 1 status is now RanToCompletion
0 commit comments