C#学习笔记【取消异步操作】

基本概念

CancellationTokenSource 是一个类,用于创建一个取消令牌 (CancellationToken),并通过该令牌来通知一个或多个异步操作取消请求。CancellationToken 是一个结构体,用于传递取消通知。

创建 CancellationTokenSource

首先,你需要创建一个 CancellationTokenSource 对象。

1
2
3
4
5
6
7
8
9
10
11
using System.Threading;

public class CancellationTokenExample
{
private CancellationTokenSource tokenSource;

public void Initialize()
{
tokenSource = new CancellationTokenSource();
}
}

获取 CancellationToken

从 CancellationTokenSource 获取 CancellationToken 对象。

1
2
3
4
5
6
7
8
9
10
11
12
using System.Threading;

public class CancellationTokenExample
{
private CancellationTokenSource tokenSource;

public void Initialize()
{
tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
}
}

在异步方法中使用 CancellationToken

在异步方法中使用 CancellationToken 来检查取消请求,并在需要时抛出 OperationCanceledException。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
using System;
using System.Threading;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks; // 如果使用 UniTask

public class CancellationTokenExample : MonoBehaviour
{
private CancellationTokenSource tokenSource;

public async void StartLongRunningTask()
{
Initialize();
CancellationToken token = tokenSource.Token;

try
{
await LongRunningTask(token);
}
catch (OperationCanceledException)
{
Debug.Log("任务已被取消");
}
}

private async UniTask LongRunningTask(CancellationToken token)
{
for (int i = 0; i < 10; i++)
{
token.ThrowIfCancellationRequested(); // 检查取消请求并抛出异常

// 模拟长时间运行的任务
await UniTask.Delay(1000, cancellationToken: token);

Debug.Log($"任务进行中: 第 {i + 1} 次");
}
}

private void Initialize()
{
tokenSource = new CancellationTokenSource();
}

private void OnClickCancelBtn()
{
if (tokenSource != null)
{
tokenSource.Cancel();
tokenSource.Dispose();
tokenSource = null;
}
}

void Start()
{
StartLongRunningTask();
}

void OnDestroy()
{
if (tokenSource != null)
{
tokenSource.Cancel();
tokenSource.Dispose();
}
}
}

详细步骤

创建 CancellationTokenSource:

声明一个 CancellationTokenSource 对象。

1
private CancellationTokenSource tokenSource;

初始化 CancellationTokenSource:

在某个方法中(例如 Start 方法)初始化 CancellationTokenSource。

1
2
3
4
private void Initialize()
{
tokenSource = new CancellationTokenSource();
}

获取 CancellationToken:

从 CancellationTokenSource 获取 CancellationToken 对象。

1
CancellationToken token = tokenSource.Token;

在异步方法中使用 CancellationToken:

在异步方法中,使用 token.ThrowIfCancellationRequested() 检查是否有取消请求。如果有取消请求,会抛出 OperationCanceledException。同时,在需要取消的异步操作中传递 CancellationToken。

1
2
3
4
5
6
7
8
9
10
private async UniTask LongRunningTask(CancellationToken token)
{
for (int i = 0; i < 10; i++)
{
token.ThrowIfCancellationRequested();
await UniTask.Delay(1000, cancellationToken: token);
Debug.Log($"任务进行中: 第 {i + 1} 次");
}
}

取消任务:

在某个事件处理方法中(例如按钮点击事件),调用 tokenSource.Cancel() 来取消任务,并释放资源。

1
2
3
4
5
6
7
8
9
private void OnClickCancelBtn()
{
if (tokenSource != null)
{
tokenSource.Cancel();
tokenSource.Dispose();
tokenSource = null;
}
}

确保资源正确释放:

在对象销毁时确保取消令牌被正确释放,以避免内存泄漏。

1
2
3
4
5
6
7
8
void OnDestroy()
{
if (tokenSource != null)
{
tokenSource.Cancel();
tokenSource.Dispose();
}
}

总结

  • 创建 CancellationTokenSource:用于生成取消令牌。
  • 获取 CancellationToken:从 CancellationTokenSource 获取令牌。
  • 在异步方法中使用 CancellationToken:检查取消请求并抛出异常。
  • 取消任务:调用 CancellationTokenSource.Cancel() 来取消任务。
  • 确保资源正确释放:在对象销毁时释放 CancellationTokenSource 资源。
    通过这些步骤,你可以在 C# 中有效地使用 CancellationTokenSource 来取消异步操作,特别是在 Unity 环境中处理长时间运行的任务时。