Nasıl Yapılır: Yoklama ile İptal İsteklerini Dinleme
Aşağıdaki örnek, kullanıcı kodunun bir iptal belirtecini düzenli aralıklarla yoklayıp çağırma iş parçacığından iptal istenip istenmediğini görmek için bir yol gösterir. Bu örnekte türü kullanılırSystem.Threading.Tasks.Task, ancak aynı desen doğrudan tür veya System.Threading.Thread tür tarafından System.Threading.ThreadPool oluşturulan zaman uyumsuz işlemler için de geçerlidir.
Örnek
Yoklama, Boole IsCancellationRequested özelliğinin değerini düzenli aralıklarla okuyabilen bir tür döngü veya özyinelemeli kod gerektirir. türünü kullanıyorsanız System.Threading.Tasks.Task ve çağıran iş parçacığında görevin tamamlanmasını bekliyorsanız, özelliğini denetlemek ve özel durumu atmak için yöntemini kullanabilirsiniz ThrowIfCancellationRequested . Bu yöntemi kullanarak, bir isteğe yanıt olarak doğru özel durumun oluştuğundan emin olursunuz. kullanıyorsanız Task, bu yöntemi çağırmak el ile oluşturmaktan OperationCanceledExceptiondaha iyidir. Özel durum oluşturmanız gerekmediyse, özelliği denetleyebilirsiniz ve özelliği ise true
yönteminden dönebilirsiniz.
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 col = 0; col < rect.columns && !token.IsCancellationRequested; col++) {
// Assume that we know that the inner loop is very fast.
// Therefore, polling once per column in the outer loop condition
// is sufficient.
for (int row = 0; row < rect.rows; row++) {
// Simulating work.
Thread.SpinWait(5_000);
Console.Write("{0},{1} ", col, row);
}
}
if (token.IsCancellationRequested) {
// Cleanup or undo here if necessary...
Console.WriteLine("\r\nOperation canceled");
Console.WriteLine("Press any key to exit.");
// If using Task:
// token.ThrowIfCancellationRequested();
}
}
}
Imports System.Threading
Imports System.Threading.Tasks
Public Structure Rectangle
Public columns As Integer
Public rows As Integer
End Structure
Class CancelByPolling
Shared Sub Main()
Dim tokenSource As New CancellationTokenSource()
' Toy object for demo purposes
Dim rect As New Rectangle()
rect.columns = 1000
rect.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(Sub() 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(Sub() PollByTimeSpan(tokenSource.Token), tokenSource.Token)
Console.WriteLine("Press 'c' to cancel")
If Console.ReadKey(True).KeyChar = "c"c Then
tokenSource.Cancel()
Console.WriteLine("Press any key to exit.")
End If
Console.ReadKey()
tokenSource.Dispose()
End Sub
Shared Sub NestedLoops(ByVal rect As Rectangle, ByVal token As CancellationToken)
Dim col As Integer
For col = 0 To rect.columns - 1
' Assume that we know that the inner loop is very fast.
' Therefore, polling once per column in the outer loop condition
' is sufficient.
For col As Integer = 0 To rect.rows - 1
' Simulating work.
Thread.SpinWait(5000)
Console.Write("0',1' ", x, y)
Next
Next
If token.IsCancellationRequested = True Then
' Cleanup or undo here if necessary...
Console.WriteLine(vbCrLf + "Operation canceled")
Console.WriteLine("Press any key to exit.")
' If using Task:
' token.ThrowIfCancellationRequested()
End If
End Sub
End Class
Çağırma ThrowIfCancellationRequested son derece hızlıdır ve döngülerde önemli ek yük oluşturmaz.
çağrısı ThrowIfCancellationRequestedyapıyorsanız, yalnızca özel durum oluşturmanın IsCancellationRequested yanı sıra iptale yanıt olarak yapmanız gereken başka işleriniz varsa özelliği açıkça denetlemeniz gerekir. Bu örnekte, kodun özelliğine aslında iki kez erişdiğini görebilirsiniz: açık erişimde bir kez ve yönteminde ThrowIfCancellationRequested tekrar. Ancak özelliği okuma IsCancellationRequested eylemi erişim başına yalnızca bir geçici okuma yönergesi içerdiğinden, çift erişim performans açısından önemli değildir. yine de el ile atmak yerine yöntemini çağırmak OperationCanceledExceptiontercih edilir.
Ayrıca bkz.
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin