-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathCancellationTokenAwaiter.cs
54 lines (48 loc) · 2.12 KB
/
CancellationTokenAwaiter.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//-------------------
// Nabbed from Medium.com:
// https://medium.com/@cilliemalan/how-to-await-a-cancellation-token-in-c-cbfc88f28fa2
//-------------------
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading;
namespace ReachableGames
{
public static class AsyncExtensions
{
/// <summary>
/// Allows a cancellation token to be awaited.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public static CancellationTokenAwaiter GetAwaiter(this CancellationToken ct)
{
// return our special awaiter
return new CancellationTokenAwaiter
{
CancellationToken = ct
};
}
/// <summary>
/// The awaiter for cancellation tokens.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public struct CancellationTokenAwaiter : INotifyCompletion, ICriticalNotifyCompletion
{
internal CancellationToken CancellationToken;
public CancellationTokenAwaiter(CancellationToken cancellationToken) => CancellationToken = cancellationToken;
// called by compiler generated/.net internals to check if the task has completed.
public bool IsCompleted => CancellationToken.IsCancellationRequested;
// The compiler will generate stuff that hooks in here. We hook those methods directly into the cancellation token.
public void OnCompleted(Action continuation) => CancellationToken.Register(continuation);
public void UnsafeOnCompleted(Action continuation) => CancellationToken.Register(continuation);
public object GetResult()
{
// this is called by compiler generated methods when the task has completed. Instead of returning a result, we just throw an exception.
if (IsCompleted)
throw new OperationCanceledException();
else
throw new InvalidOperationException("The cancellation token has not yet been cancelled.");
}
}
}
}