【你不一定知晓的】C#取消异步操作
2021-06-09 17:04
标签:部分 key 发布者 wait sdn oid csharp value complete 在.Net和C#中运行异步代码相当简单,因为我们有时候需要取消正在进行的异步操作,通过本文,可以掌握 通过CancellationToken取消任务(包括non-cancellable任务)。 已经不再推荐这种方式来完成异步和长时间运行的操作,但是大部分概念在现在依旧可以使用。 简单异步调用代码: 像上面代码一样执行取消命令 : 【你不一定知晓的】C#取消异步操作 标签:部分 key 发布者 wait sdn oid csharp value complete 原文地址:https://www.cnblogs.com/lonelyxmas/p/10646655.html
早期
private void BackgroundLongRunningTask(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = (BackgroundWorker)sender;
for (int i = 1; i 10000; i++)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
// Do something
}
}
Task横空出世
///
public static async Task ExecuteTaskAsync()
{
Console.WriteLine(nameof(ExecuteTaskAsync));
Console.WriteLine("Result {0}", await LongRunningOperation(100));
Console.WriteLine("Press enter to continue");
Console.ReadLine();
}
敲黑板: C#取消异步操作分为
① 让代码可取消(Cancellable)
///
② 触发取消命令
// 以下代码 利用 CancellationSource默认构造函数 完成超时取消
public static async Task ExecuteTaskWithTimeoutAsync(TimeSpan timeSpan)
{
Console.WriteLine(nameof(ExecuteTaskWithTimeoutAsync));
using (var cancellationTokenSource = new CancellationTokenSource(timeSpan))
{
try
{
var result = await LongRunningCancellableOperation(500, cancellationTokenSource.Token);
Console.WriteLine("Result {0}", result);
}
catch (TaskCanceledException)
{
Console.WriteLine("Task was cancelled");
}
}
Console.WriteLine("Press enter to continue");
Console.ReadLine();
}
------------------------------------------------------------------------------------------------------------
附①: 高阶操作,完成手动取消:
public static async Task ExecuteManuallyCancellableTaskAsync()
{
Console.WriteLine(nameof(ExecuteManuallyCancellableTaskAsync));
using (var cancellationTokenSource = new CancellationTokenSource())
{
// Creating a task to listen to keyboard key press
var keyBoardTask = Task.Run(() =>
{
Console.WriteLine("Press enter to cancel");
Console.ReadKey();
// Cancel the task
cancellationTokenSource.Cancel();
});
try
{
var longRunningTask = LongRunningCancellableOperation(500, cancellationTokenSource.Token);
var result = await longRunningTask;
Console.WriteLine("Result {0}", result);
Console.WriteLine("Press enter to continue");
}
catch (TaskCanceledException)
{
Console.WriteLine("Task was cancelled");
}
await keyBoardTask;
}
}
// 以上是一个控制台程序,异步接收控制台输入,发出取消命令。附②:高阶操作,取消 non-Cancellable任务 :
private static async Taskdecimal> LongRunningOperationWithCancellationTokenAsync(int loop, CancellationToken cancellationToken)
{
// We create a TaskCompletionSource of decimal
var taskCompletionSource = new TaskCompletionSourcedecimal>();
// Registering a lambda into the cancellationToken
cancellationToken.Register(() =>
{
// We received a cancellation message, cancel the TaskCompletionSource.Task
taskCompletionSource.TrySetCanceled();
});
var task = LongRunningOperation(loop);
// Wait for the first task to finish among the two
var completedTask = await Task.WhenAny(task, taskCompletionSource.Task);
return await completedTask;
}
public static async Task CancelANonCancellableTaskAsync()
{
Console.WriteLine(nameof(CancelANonCancellableTaskAsync));
using (var cancellationTokenSource = new CancellationTokenSource())
{
// Listening to key press to cancel
var keyBoardTask = Task.Run(() =>
{
Console.WriteLine("Press enter to cancel");
Console.ReadKey();
// Sending the cancellation message
cancellationTokenSource.Cancel();
});
try
{
// Running the long running task
var longRunningTask = LongRunningOperationWithCancellationTokenAsync(100, cancellationTokenSource.Token);
var result = await longRunningTask;
Console.WriteLine("Result {0}", result);
Console.WriteLine("Press enter to continue");
}
catch (TaskCanceledException)
{
Console.WriteLine("Task was cancelled");
}
await keyBoardTask;
}
}
总结:
上一篇:Restful API 特性详解