在 C# 中,CancellationTokenSource 是一个用于创建和管理 CancellationToken(取消标记)的类。它提供了一种简单的方式来请求取消异步或多线程操作。
看一下Cancel的顺序
C#static void Main(string[] args)
{
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken cancellationToken = cts.Token;
cancellationToken.Register(() =>
{
Console.WriteLine("Cancel1...");
});
cancellationToken.Register(() =>
{
Console.WriteLine("Cancel2...");
});
cancellationToken.Register(state =>
{
Console.WriteLine("Cancel3..." + state.ToString());
}, "OK");
Console.WriteLine("开始...");
cts.Cancel();
}
取消异步操作:在进行异步操作时,可能需要提供取消操作的能力,以便在需要时中止操作。使用 CancellationTokenSource 创建 CancellationToken,并将其传递给异步方法,然后在需要取消操作时,调用 CancellationTokenSource 的 Cancel() 方法。
C#static async Task Main(string[] args)
{
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken cancellationToken = cts.Token;
//启动任务
Task asyncOperationTask = DoAsyncOption(cancellationToken);
await Task.Delay(2000);
cts.Cancel();
}
async static Task DoAsyncOption(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
Console.WriteLine("do...");
await Task.Delay(500, cancellationToken);
}
}
取消多线程操作:在多线程环境中,有时需要在另一个线程中通知某个线程进行取消。CancellationTokenSource 可以用来创建 CancellationToken,并将其传递给需要取消的线程。
C#static CancellationTokenSource cts = new CancellationTokenSource();
static CancellationToken cancellationToken;
static async Task Main(string[] args)
{
cancellationToken = cts.Token;
//启动任务
Task asyncOperationTask = DoAsyncOption();
//开启管理任务
await Do();
while (true)
{
}
}
async static Task Do()
{
int x = 0;
while (true)
{
x++;
if (x == 10)
{
cts.Cancel();
}
await Task.Delay(500);
}
}
async static Task DoAsyncOption()
{
while (!cancellationToken.IsCancellationRequested)
{
Console.WriteLine("do...");
await Task.Delay(500);
}
}
超时处理:在执行某些操作时,可以设置一个超时,如果操作在指定时间内未完成,就取消它。
C#static async Task Main(string[] args)
{
CancellationTokenSource cts = new CancellationTokenSource(5000);//设置超时
CancellationToken cancellationToken = cts.Token;
Task task = DoOperationWithTimeout(cts.Token);
while (true)
{
}
}
async static Task DoOperationWithTimeout(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
Console.WriteLine("do...");
await Task.Delay(500);
}
}
取消链:CancellationTokenSource 提供了 CreateLinkedTokenSource 方法,可以将多个 CancellationToken 组合成一个联动的取消标记。只要其中一个标记被取消,链中的所有标记都会收到取消请求。
C#static async Task Main(string[] args)
{
CancellationTokenSource cts = new CancellationTokenSource(5000);//设置超时
CancellationToken cancellationToken = cts.Token;
DoOperationWithLinkedToken(cancellationToken);
await Task.Delay(5000);
cts.Cancel();
while (true)
{
}
}
static async void DoOperationWithLinkedToken(CancellationToken cancellationToken)
{
//任意一个cancel都会cancel
using (var cts1 = new CancellationTokenSource())
using (var cts2 = new CancellationTokenSource())
{
using (var combinedCts = CancellationTokenSource.CreateLinkedTokenSource(cts1.Token, cts2.Token, cancellationToken))
{
while (!combinedCts.IsCancellationRequested)
{
Console.WriteLine("do...");
await Task.Delay(500);
}
}
}
}
监视取消请求:可以通过 CancellationTokenSource 的 Token 属性来监视取消请求,并在取消时执行相应的操作。
C#static async Task Main(string[] args)
{
CancellationTokenSource cts = new CancellationTokenSource(5000);//设置超时
CancellationToken cancellationToken = cts.Token;
MonitorCancellation(cancellationToken);
for (int i = 0; i < 10; i++)
{
if (cancellationToken.IsCancellationRequested)
{
break;
}
Console.WriteLine("do...");
await Task.Delay(1000);
}
cts.Cancel();
while (true)
{
}
}
static void MonitorCancellation(CancellationToken cancellationToken)
{
cancellationToken.Register(() => Console.WriteLine("Cancellation requested."));
}
使用 IsCancellationRequested
来判断线程比用自己自定义一个变量是否应该退出有以下好处:
IsCancellationRequested
属性是 CancellationToken 结构的一部分。CancellationToken 是用于协调线程和任务之间取消操作的一种机制。它可以在多个线程之间安全地传递,而不需要使用额外的同步机制。这种方式可以确保线程在需要退出时得到通知。在 .NET 中,如果你需要在多线程环境下管理任务的取消,推荐使用 CancellationToken 和 IsCancellationRequested 属性。这些属性可以确保任务能够及时响应取消请求,避免出现意外的运行时错误。当然,如果你的场景比较特殊,或者需要实现一些非标准化的取消机制,也可以使用自定义的取消机制,但需要注意这种方式可能会增加代码的复杂性和难度。
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!