回答編集履歴
2
追記とちょっと修正
answer
CHANGED
@@ -53,7 +53,7 @@
|
|
53
53
|
|
54
54
|
{
|
55
55
|
var scan = _adapter.ScanAsync(); // まずawaitをつけないで実行し、IAsyncActionを取得
|
56
|
-
this._asyncTask = scan; 先にフィールドとか外部に渡す
|
56
|
+
this._asyncTask = scan; // 先にフィールドとか外部に渡す
|
57
57
|
await scan; // その後await
|
58
58
|
}
|
59
59
|
|
@@ -63,13 +63,14 @@
|
|
63
63
|
}
|
64
64
|
```
|
65
65
|
|
66
|
-
さらに別の方法をとして、通常のTaskのように、CancellationTokenを使ったキャンセル機構に一元化したい場合に、CancellationToken.Register()メソッドを利用することもできます。
|
66
|
+
~~さらに別の方法をとして、通常のTaskのように、CancellationTokenを使ったキャンセル機構に一元化したい場合に、CancellationToken.Register()メソッドを利用することもできます。~~
|
67
|
+
以下はもっと良い方法を教えていただいたので末尾に追記してます。
|
67
68
|
|
68
69
|
```csharp
|
69
70
|
async Task GetintValue(CancellationToken token)
|
70
71
|
{
|
71
72
|
var scan = _adapter.ScanAsync(); // まずawaitをつけないで実行
|
72
|
-
token.Register(() => scan.Cancel()); tokenがCancel状態になったときにScanAsyncをキャンセルするように登録
|
73
|
+
token.Register(() => scan.Cancel()); // tokenがCancel状態になったときにScanAsyncをキャンセルするように登録
|
73
74
|
await scan; // その後await
|
74
75
|
}
|
75
76
|
|
@@ -77,4 +78,21 @@
|
|
77
78
|
{
|
78
79
|
this.cts.Cancel(); // 普通のTaskのようにCancellationTokenSourceのCancel()メソッドを呼んでキャンセルできる
|
79
80
|
}
|
81
|
+
```
|
82
|
+
|
83
|
+
---
|
84
|
+
さらに追記
|
85
|
+
IAsyncActionをTaskとして取り扱える拡張メソッドが存在することを教えていただきました。(asmさんありがとうございます)
|
86
|
+
これを利用するとCancellationTokenを利用するキャンセル処理を自然に実装できます。async/awaitやTaskと組み合わせる場合では、これが一番良い方法だと思います。
|
87
|
+
|
88
|
+
```csharp
|
89
|
+
async Task GetintValue(CancellationToken token) // 引数で受け取って
|
90
|
+
{
|
91
|
+
await _adapter.ScanAsync().AsTask(token); // AsTaskメソッドにtokenを渡して、awaitするだけ
|
92
|
+
}
|
93
|
+
|
94
|
+
// ...Cancelボタン
|
95
|
+
{
|
96
|
+
this.cts.Cancel(); // 普通のTaskのようにCancellationTokenSourceのCancel()メソッドを呼んでキャンセルできる
|
97
|
+
}
|
80
98
|
```
|
1
IAsyncActionだった
answer
CHANGED
@@ -39,4 +39,42 @@
|
|
39
39
|
|
40
40
|
```
|
41
41
|
|
42
|
-
あと、ThrowIfCancellationRequested()メソッドを用いてキャンセルする場合、非同期メソッドのTaskの状態がRunningでもCompletedでもなくCanceled状態になるため、キャンセルされたということが明確になるためオススメです。
|
42
|
+
あと、ThrowIfCancellationRequested()メソッドを用いてキャンセルする場合、非同期メソッドのTaskの状態がRunningでもCompletedでもなくCanceled状態になるため、キャンセルされたということが明確になるためオススメです。
|
43
|
+
|
44
|
+
---
|
45
|
+
追記
|
46
|
+
|
47
|
+
TaskではなくIAsyncActionの非同期キャンセルということだったので追記します、おそらくTaskより簡単に処理できます。(UWP関係はほぼ触ったことないので間違ってるかもしれません)
|
48
|
+
|
49
|
+
IAsyncActionインターフェースはそれ自体がCancel()メソッドを持っており、かつAwaitableになっているものです。
|
50
|
+
awaitを使って非同期メソッドのフローに組み込む前に、それ自身のキャンセル機構を呼び出せるように設計するだけで良いです。
|
51
|
+
```csharp
|
52
|
+
private IAsyncInfo _asyncTask; // とりあえず非同期処理そのものを監視するための変数
|
53
|
+
|
54
|
+
{
|
55
|
+
var scan = _adapter.ScanAsync(); // まずawaitをつけないで実行し、IAsyncActionを取得
|
56
|
+
this._asyncTask = scan; 先にフィールドとか外部に渡す
|
57
|
+
await scan; // その後await
|
58
|
+
}
|
59
|
+
|
60
|
+
// ...Cancelボタン
|
61
|
+
{
|
62
|
+
this._asyncTask?.Cancel(); // IAsyncInfoのCancel()メソッドを呼ぶだけ
|
63
|
+
}
|
64
|
+
```
|
65
|
+
|
66
|
+
さらに別の方法をとして、通常のTaskのように、CancellationTokenを使ったキャンセル機構に一元化したい場合に、CancellationToken.Register()メソッドを利用することもできます。
|
67
|
+
|
68
|
+
```csharp
|
69
|
+
async Task GetintValue(CancellationToken token)
|
70
|
+
{
|
71
|
+
var scan = _adapter.ScanAsync(); // まずawaitをつけないで実行
|
72
|
+
token.Register(() => scan.Cancel()); tokenがCancel状態になったときにScanAsyncをキャンセルするように登録
|
73
|
+
await scan; // その後await
|
74
|
+
}
|
75
|
+
|
76
|
+
// ...Cancelボタン
|
77
|
+
{
|
78
|
+
this.cts.Cancel(); // 普通のTaskのようにCancellationTokenSourceのCancel()メソッドを呼んでキャンセルできる
|
79
|
+
}
|
80
|
+
```
|