コピペ投稿者:名無しさん
投稿者ID:NIB/YAMP
コピペ投稿日時:2021/07/09 17:57
コピペ投稿日時:2021/07/09 17:57
方法: ポーリングによりキャンセル要求を待機する
2017/03/30
次の例は、ユーザー コードで取り消しトークンを定期的にポーリングし、呼び出し元のスレッドから取り消しが要求されているかどうかを確認する 1 つの方法を示しています。 この例では System.Threading.Tasks.Task 型を使用しますが、System.Threading.ThreadPool 型または System.Threading.Thread 型で直接作成される非同期操作にも同じパターンが適用されます。
例
ポーリングには、ブール IsCancellationRequested プロパティの値を定期的に読み取ることができる、ある種のループまたは再帰的なコードが必要になります。 System.Threading.Tasks.Task 型を使用し、タスクが呼び出し元スレッドで完了するまで待機する場合は、ThrowIfCancellationRequested スレッドを使用してプロパティを確認し、例外をスローすることができます。 このメソッドを使用することで、要求に応じて、正しい例外がスローされるようになります。 Task を使用する場合は、OperationCanceledException を手動でスローするよりもこのスレッドを呼び出す方が効果的です。 例外をスローする必要がない場合は、単にプロパティを確認し、プロパティが true である場合はメソッドから制御を返すことができます。
C#
コピー
using System;
using System.Threading;
using System.Threading.Tasks;
public struct Rectangle
{
public int columns;
public int rows;
}
class CancelByPolling
{
static void Main()
{
var tokenSource = new CancellationTokenSource();
// Toy object for demo purposes
Rectangle rect = new Rectangle() { columns = 1000, rows = 500 };
// Simple cancellation scenario #1. Calling thread does not wait
// on the task to complete, and the user delegate simply returns
// on cancellation request without throwing.
Task.Run(() => NestedLoops(rect, tokenSource.Token), tokenSource.Token);
// Simple cancellation scenario #2. Calling thread does not wait
// on the task to complete, and the user delegate throws
// OperationCanceledException to shut down task and transition its state.
// Task.Run(() => PollByTimeSpan(tokenSource.Token), tokenSource.Token);
Console.WriteLine("Press 'c' to cancel");
if (Console.ReadKey(true).KeyChar == 'c') {
tokenSource.Cancel();
Console.WriteLine("Press any key to exit.");
}
Console.ReadKey();
tokenSource.Dispose();
}
static void NestedLoops(Rectangle rect, CancellationToken token)
{
for (int x = 0; x < rect.columns && !token.IsCancellationRequested; x++) {
for (int y = 0; y < rect.rows; y++) {
// Simulating work.
Thread.SpinWait(5000);
Console.Write("{0},{1} ", x, y);
}
// Assume that we know that the inner loop is very fast.
// Therefore, checking once per row is sufficient.
if (token.IsCancellationRequested) {
// Cleanup or undo here if necessary...
Console.WriteLine("\r\nCancelling after row {0}.", x);
Console.WriteLine("Press any key to exit.");
// then...
break;
// ...or, if using Task:
// token.ThrowIfCancellationRequested();
}
}
}
}
ThrowIfCancellationRequested の呼び出しは非常に高速で、ループで大きなオーバーヘッドが発生することはありません。
ThrowIfCancellationRequested を呼び出す場合に、例外をスローするだけではなく、取り消しに応じて他の作業を行う場合は IsCancellationRequested プロパティを明示的に確認するだけで済みます。 この例では、コードで実際にプロパティに 2 回アクセスするのがわかります。つまり、明示的なアクセスで 1 回、ThrowIfCancellationRequested メソッドでもう 1 回です。 ただし、IsCancellationRequested プロパティの読み取り操作ではアクセスごとに 1 つの volatile 読み取りのみが含まれるため、パフォーマンスの観点からは二重アクセスは重要ではありません。 それでも、OperationCanceledException を手動でスローするよりメソッドを呼び出すことをお勧めします。
2017/03/30
次の例は、ユーザー コードで取り消しトークンを定期的にポーリングし、呼び出し元のスレッドから取り消しが要求されているかどうかを確認する 1 つの方法を示しています。 この例では System.Threading.Tasks.Task 型を使用しますが、System.Threading.ThreadPool 型または System.Threading.Thread 型で直接作成される非同期操作にも同じパターンが適用されます。
例
ポーリングには、ブール IsCancellationRequested プロパティの値を定期的に読み取ることができる、ある種のループまたは再帰的なコードが必要になります。 System.Threading.Tasks.Task 型を使用し、タスクが呼び出し元スレッドで完了するまで待機する場合は、ThrowIfCancellationRequested スレッドを使用してプロパティを確認し、例外をスローすることができます。 このメソッドを使用することで、要求に応じて、正しい例外がスローされるようになります。 Task を使用する場合は、OperationCanceledException を手動でスローするよりもこのスレッドを呼び出す方が効果的です。 例外をスローする必要がない場合は、単にプロパティを確認し、プロパティが true である場合はメソッドから制御を返すことができます。
C#
コピー
using System;
using System.Threading;
using System.Threading.Tasks;
public struct Rectangle
{
public int columns;
public int rows;
}
class CancelByPolling
{
static void Main()
{
var tokenSource = new CancellationTokenSource();
// Toy object for demo purposes
Rectangle rect = new Rectangle() { columns = 1000, rows = 500 };
// Simple cancellation scenario #1. Calling thread does not wait
// on the task to complete, and the user delegate simply returns
// on cancellation request without throwing.
Task.Run(() => NestedLoops(rect, tokenSource.Token), tokenSource.Token);
// Simple cancellation scenario #2. Calling thread does not wait
// on the task to complete, and the user delegate throws
// OperationCanceledException to shut down task and transition its state.
// Task.Run(() => PollByTimeSpan(tokenSource.Token), tokenSource.Token);
Console.WriteLine("Press 'c' to cancel");
if (Console.ReadKey(true).KeyChar == 'c') {
tokenSource.Cancel();
Console.WriteLine("Press any key to exit.");
}
Console.ReadKey();
tokenSource.Dispose();
}
static void NestedLoops(Rectangle rect, CancellationToken token)
{
for (int x = 0; x < rect.columns && !token.IsCancellationRequested; x++) {
for (int y = 0; y < rect.rows; y++) {
// Simulating work.
Thread.SpinWait(5000);
Console.Write("{0},{1} ", x, y);
}
// Assume that we know that the inner loop is very fast.
// Therefore, checking once per row is sufficient.
if (token.IsCancellationRequested) {
// Cleanup or undo here if necessary...
Console.WriteLine("\r\nCancelling after row {0}.", x);
Console.WriteLine("Press any key to exit.");
// then...
break;
// ...or, if using Task:
// token.ThrowIfCancellationRequested();
}
}
}
}
ThrowIfCancellationRequested の呼び出しは非常に高速で、ループで大きなオーバーヘッドが発生することはありません。
ThrowIfCancellationRequested を呼び出す場合に、例外をスローするだけではなく、取り消しに応じて他の作業を行う場合は IsCancellationRequested プロパティを明示的に確認するだけで済みます。 この例では、コードで実際にプロパティに 2 回アクセスするのがわかります。つまり、明示的なアクセスで 1 回、ThrowIfCancellationRequested メソッドでもう 1 回です。 ただし、IsCancellationRequested プロパティの読み取り操作ではアクセスごとに 1 つの volatile 読み取りのみが含まれるため、パフォーマンスの観点からは二重アクセスは重要ではありません。 それでも、OperationCanceledException を手動でスローするよりメソッドを呼び出すことをお勧めします。
コメント一覧
要はあれだろ?
ボーリングでいいスコア取れるようにするにはって事だろ?