gpt4 book ai didi

c# - 如何取消任务但等到它完成?

转载 作者:太空狗 更新时间:2023-10-29 23:14:07 26 4
gpt4 key购买 nike

我有线程任务,它在循环中执行一些操作:

static void TaskAction(CancellationToken ct)
{
while (SomeCondition())
{
DoSomeSeriousJob();
ct.ThrowIfCancellationRequested();
}
}

static void DoSomeSeriousJob()
{
Console.WriteLine("Serious job started");
Thread.Sleep(5000);
Console.WriteLine("Serious job done");
}

我启动它然后在一段时间后取消:

    var cts = new CancellationTokenSource();
var task = Task.Factory.StartNew(() => TaskAction(cts.Token), cts.Token);
Thread.Sleep(1000);
cts.Cancel();

这个操作必须正确完成,我不想打断它。但我想向我的任务发送取消请求并等待它正确完成(我的意思是它到达代码中的某个点)。我尝试了以下方法:

1。等待(CancellationToken ct)

try
{
task.Wait(cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Task cancelled");
}
// Must be joined here.

在这种情况下,程序会立即从 Wait() 返回。任务会继续运行,直到 ThrowIfCancellationRequested() 但如果主线程退出,任务也会被中断。

2。等待()

try
{
task.Wait();
}
catch (OperationCanceledException)
{
Console.WriteLine("Task cancelled");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}

这里主线程等待完成,但最后 AggregateException 出现 InnerException = TaskCancelledException(不是 OperationCancelledException).

3。检查 IsCancellationRequested() 没有异常

static void TaskAction(CancellationToken ct)
{
while (SomeCondition())
{
DoSomeSeriousJob();
if (ct.IsCancellationRequested)
break;
}
}
// ...
task.Wait();

在这种情况下,不会出现异常,但任务最终会获得 RanToCompletion 状态。当 SomeCodition() 开始返回 false 时,这与正确完成没有区别。

所有这些问题都有简单的解决方法,但我想知道,我可能遗漏了什么?有人可以建议我更好的解决方案吗?

最佳答案

如果你想等待任务同步完成(或被取消),你可以试试这个:

cts.Cancel();
Task.Run(async () => {
try {
await task;
}
catch (OperationCanceledException ex) {
// ...
}
).Wait();

这样您就可以直接捕获 OperationCanceledException 而不是捕获 AggregateException。

编辑:

等待(CanecllationToken)

此方法不适用于该目的。 MSDN声明:

Waits for the Task to complete execution. The wait terminates if a cancellation token is canceled before the task completes.

等待()

您可以使用此方法,但如您所见,您应该期待 AggregateException 而不是 OperationCanceledException。它也在 documents 中指定。的方法。

The AggregateException.InnerExceptions collection contains a TaskCanceledException object.

因此在这种方法中,为了确保操作被取消,您可以检查内部预期是否包含 TaskCanceledException。

检查 IsCancellationRequested() 没有异常

这样一来,很明显没有异常抛出,也不知道操作是否取消了。

如果您不想同步等待,一切都会按预期进行:

cts.Cancel();
try {
await task;
}
catch (OperationCanceledException ex) {
// ...
}

关于c# - 如何取消任务但等到它完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29924284/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com