كيفية القيام بما يلي: انصات لطلبات الإلغاء بواسطة استقصاء
يوضح المثال التالي طريقة واحدة أن تعليمات برمجية للمستخدم أن الاستقصاء إلغاء إلى ken في فترات زمنية منتظمة إلى معرفة ما إذا تم طلب الإلغاء من مؤشر ترابط استدعاء. يستخدم هذا المثال System.Threading.Tasks.Taskالنوع، ولكن نقش نفسه ينطبق على غير متزامن العمليات التي تم إنشاؤها بشكل مباشر System.Threading.ThreadPoolنوع أو System.Threading.Threadالنوع.
مثال
استقصاء يتطلب نوع من تكرار حلقي أو متداخل تعليمات برمجية دورياً التي يمكن قراءة القيمة منطقية IsCancellationRequestedخاصية. إذا كنت تستخدم System.Threading.Tasks.Taskالنوع والتي تنتظر مهمة إلى كاملة تشغيل مؤشر ترابط استدعاء، يمكنك استخدام ThrowIfCancellationRequestedأسلوب إلى التحقق من خاصية وقم بطرح استثناء. باستخدام رقم هو الأسلوب، يمكنك التأكد الاستثناء الصحيح هو طرح استجابة لطلب. إذا كنت تستخدم Task، ثم قم باستدعاء هذا أسلوب هو أفضل من طرح يدوياً OperationCanceledException. إذا لم يكن لطرح استثناء، فيمكنك فقط فحص من خاصية والعودة من الأسلوب في حالة $ $ $ $ خاصية هو true.
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.Factory.StartNew(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.Factory.StartNew(Sub() PollByTimeSpan(tokenSource.Token), tokenSource.Token)
Console.WriteLine("Press 'c' to cancel")
If Console.ReadKey().KeyChar = "c"c Then
tokenSource.Cancel()
Console.WriteLine("Press any key to exit.")
End If
Console.ReadKey()
End Sub
Shared Sub NestedLoops(ByVal rect As Rectangle, ByVal token As CancellationToken)
For x As Integer = 0 To rect.columns
For y As Integer = 0 To rect.rows
' Simulating work.
Thread.SpinWait(5000)
Console.Write("0' end block,1' end block ", x, y)
Next
' Assume that we know that the inner loop is very fast.
' Therefore, checking once per row is sufficient.
If token.IsCancellationRequested = True Then
' Cleanup or undo here if necessary...
Console.WriteLine("\r\nCancelling after row 0' end block.", x)
Console.WriteLine("Press any key to exit.")
' then...
Exit For
' ...or, if using Task:
' token.ThrowIfCancellationRequested()
End If
Next
End Sub
End Class
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.Factory.StartNew(() => 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.Factory.StartNew(() => PollByTimeSpan(tokenSource.Token), tokenSource.Token);
Console.WriteLine("Press 'c' to cancel");
if (Console.ReadKey().KeyChar == 'c')
{
tokenSource.Cancel();
Console.WriteLine("Press any key to exit.");
}
Console.ReadKey();
}
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خاصية إذا كان لديك عمل غير ذلك للقيام باستجابة للإلغاء بالإضافة إلى طرح استثناء. في هذا مثال، يمكن التحقق من أن التعليمة البرمجية فعلياً وصول خاصية مرتين: مرة في الوصول الصريح و مرة أخرى في ThrowIfCancellationRequestedالأسلوب. ولكن نظراً لأن عملية قراءة IsCancellationRequestedتتضمن خاصية متغير واحد فقط قراءة الإرشادات كل وصول، وصول مزدوجة هو غير الهامة من منظور أداء. هو لا تزال أفضل باستدعاء الأسلوب بدلاً من يدوياً الإلقاء OperationCanceledException.