使用 cancellationtoken 为用户定义的函数设置超时

Set timeout for user defined function using cancelation token

如果任务持续时间超过 3 秒,我想取消它。

第一次尝试:

public static async Task DoSomething()
{
    await Task.Delay(10000);
}

var task1 = DoSomething();
var task2 = Task.Delay(3000);

Task.WaitAny(task1, task2);

第二次尝试:

我尝试使用 cancellationToken 但它似乎不起作用。它等待功能 10 秒,似乎忽略了 3 秒延迟取消。

var cts = new CancellationTokenSource();
var token = cts.Token;
cts.CancelAfter(TimeSpan.FromSeconds(3));

await Task.Run(async () => await DoSomething(), token);

有人可以帮助我使用 cancellationToken 实现此类功能吗?

您需要将 CancellationToken 传递给 DoSomething 并在那里使用它:

public static async Task DoSomething(CancellationToken t)
{
    await Task.Delay(10000, t);
}

var cts = new CancellationTokenSource();
var token = cts.Token;
cts.CancelAfter(TimeSpan.FromSeconds(3));
try
{
    await Task.Run(async () => await DoSomething(token), token);
}
catch (OperationCanceledException ex)
{
    // canceled
}

来自docs

When a task instance observes an OperationCanceledException thrown by user code, it compares the exception's token to its associated token (the one that was passed to the API that created the Task). If they are the same and the token's IsCancellationRequested property returns true, the task interprets this as acknowledging cancellation and transitions to the Canceled state. If you do not use a Wait or WaitAll method to wait for the task, then the task just sets its status to Canceled.

但似乎 Task 过渡到 Canceled 与是否提供相同的令牌无关。

我能找到的将令牌传递给 Task.Run 与不传递令牌之间的唯一区别是,如果在任务开始执行之前请求取消,则任务不会执行,而是设置为 Canceled 状态并抛出 TaskCanceledException 异常。