Skip to content

Commit cbd0f72

Browse files
ErlendLandroBillWagner
authored andcommitted
Modern async (#955)
* Modernize C# code Task.Run instead of TaskFactory.StartNew. await instead of Wait() String interpolation instead of concatenation * Use modern async constructs async/await and Task.Run * Fix formatting * Catch OperationCanceledException when using await
1 parent 1a1e8af commit cbd0f72

File tree

2 files changed

+89
-95
lines changed

2 files changed

+89
-95
lines changed

snippets/csharp/VS_Snippets_Misc/tpl_cancellation/cs/cancel1.cs

Lines changed: 81 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -6,53 +6,55 @@
66

77
public class Example
88
{
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;
1313

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>();
1818

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);
3050

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-
5051
Console.WriteLine("Task {0} executing", t.Id);
5152
tasks.Add(t);
5253

5354
// Request cancellation from the UI thread.
5455
char ch = Console.ReadKey().KeyChar;
55-
if (ch == 'c'|| ch == 'C' ) {
56+
if (ch == 'c' || ch == 'C')
57+
{
5658
tokenSource.Cancel();
5759
Console.WriteLine("\nTask cancellation requested.");
5860

@@ -61,63 +63,59 @@ public static void Main()
6163
// if you do wait, you must enclose the call in a try-catch block to
6264
// catch the TaskCanceledExceptions that are thrown. If you do
6365
// 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+
}
6668

67-
try {
68-
Task.WaitAll(tasks.ToArray());
69+
try
70+
{
71+
await Task.WhenAll(tasks.ToArray());
6972
}
70-
catch (AggregateException e) {
71-
Console.WriteLine("\nAggregateException 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");
8176
}
8277
finally
8378
{
84-
tokenSource.Dispose();
79+
tokenSource.Dispose();
8580
}
8681

8782
// Display status of all tasks.
8883
foreach (var task in tasks)
8984
Console.WriteLine("Task {0} status is now {1}", task.Id, task.Status);
90-
}
85+
}
9186

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+
}
10096

101-
int maxIterations = 100;
97+
int maxIterations = 100;
10298

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();
113110

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+
}
121119
// The example displays output like the following:
122120
// Press any key to begin tasks...
123121
// To terminate the example, press 'c' to cancel and exit...
@@ -135,10 +133,7 @@ static void DoSomeWork(int taskNum, CancellationToken ct)
135133
// Task 2 cancelled
136134
// Task 7 cancelled
137135
//
138-
// AggregateException thrown with the following inner exceptions:
139-
// TaskCanceledException: Task 2
140-
// TaskCanceledException: Task 8
141-
// TaskCanceledException: Task 7
136+
// OperationCanceledException thrown
142137
//
143138
// Task 2 status is now Canceled
144139
// Task 1 status is now RanToCompletion

snippets/csharp/VS_Snippets_Misc/tpl_cancellation/cs/snippet02.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22
using System;
33
using System.Threading;
44
using System.Threading.Tasks;
5+
56
class Program
67
{
7-
static void Main()
8+
static async Task Main()
89
{
910
var tokenSource2 = new CancellationTokenSource();
1011
CancellationToken ct = tokenSource2.Token;
1112

12-
var task = Task.Factory.StartNew(() =>
13+
var task = Task.Run(() =>
1314
{
14-
1515
// Were we already canceled?
1616
ct.ThrowIfCancellationRequested();
1717

@@ -27,19 +27,18 @@ static void Main()
2727
}
2828

2929
}
30-
}, tokenSource2.Token); // Pass same token to StartNew.
30+
}, tokenSource2.Token); // Pass same token to Task.Run.
3131

3232
tokenSource2.Cancel();
3333

34-
// Just continue on this thread, or Wait/WaitAll with try-catch:
34+
// Just continue on this thread, or await with try-catch:
3535
try
3636
{
37-
task.Wait();
37+
await task;
3838
}
39-
catch (AggregateException e)
39+
catch (OperationCanceledException e)
4040
{
41-
foreach (var v in e.InnerExceptions)
42-
Console.WriteLine(e.Message + " " + v.Message);
41+
Console.WriteLine($"{nameof(OperationCanceledException)} thrown with message: {e.Message}");
4342
}
4443
finally
4544
{

0 commit comments

Comments
 (0)