C# 如果抛出异常,则取消所有异步方法
我玩取消令牌,我想了解它是如何工作的。我有两个异步方法(在我的示例中是两个,但理论上我可以有100个)。 如果其中一个异步方法引发异常,我想取消所有异步方法中的工作 我的想法是在调用所有方法的异常情况下取消令牌。当一个令牌被取消时,我希望其他方法停止工作,但这并没有发生C# 如果抛出异常,则取消所有异步方法,c#,async-await,task,C#,Async Await,Task,我玩取消令牌,我想了解它是如何工作的。我有两个异步方法(在我的示例中是两个,但理论上我可以有100个)。 如果其中一个异步方法引发异常,我想取消所有异步方法中的工作 我的想法是在调用所有方法的异常情况下取消令牌。当一个令牌被取消时,我希望其他方法停止工作,但这并没有发生 using System; using System.Threading; using System.Threading.Tasks; namespace CancelationTest { class Program
using System;
using System.Threading;
using System.Threading.Tasks;
namespace CancelationTest
{
class Program
{
static void Main(string[] args)
{
new Test();
Console.ReadKey();
}
}
public class Test
{
public Test()
{
Task.Run(() => MainAsync());
}
public static async Task MainAsync()
{
var cancellationTokenSource = new CancellationTokenSource();
try
{
var firstTask = FirstAsync(cancellationTokenSource.Token);
var secondTask = SecondAsync(cancellationTokenSource.Token);
Thread.Sleep(50);
Console.WriteLine("Begin");
await secondTask;
Console.WriteLine("hello");
await firstTask;
Console.WriteLine("world");
Console.ReadKey();
}
catch (OperationCanceledException e)
{
Console.WriteLine("Main OperationCanceledException cancel");
}
catch (Exception e)
{
Console.WriteLine("Main Exception + Cancel");
cancellationTokenSource.Cancel();
}
}
public static async Task FirstAsync(CancellationToken c)
{
c.ThrowIfCancellationRequested();
await Task.Delay(1000, c);
Console.WriteLine("Exception in first call");
throw new NotImplementedException("Exception in first call");
}
public static async Task SecondAsync(CancellationToken c)
{
c.ThrowIfCancellationRequested();
await Task.Delay(15000, c);
Console.WriteLine("SecondAsync is finished");
}
}
}
第二个方法完成工作并延迟任务15秒,即使第一个方法抛出异常也是如此
结果是什么:
开始
第一次调用中的异常
SecondAsync已完成
你好
主异常+取消
我希望secondAsync停止延迟并抛出OperationCancelException。
我预计会有这样的结果:
开始
第一次调用中的异常
主异常+取消
主操作取消异常取消
我哪里出错了?
为什么方法SecondAsync完全执行并且不引发异常?如果我更改SecondAsync和FirstAsync的顺序,则当令牌被取消时,Second method stop会延迟并引发异常。您需要位于被调用的方法可以访问的范围内,并且您需要调用CancellationTokenSource.Cancel()
以取消使用该源的所有操作
您还可以调用
CancellationTokenSource.CancelAfter(TimeSpan)
以在延迟时取消它。,因为代码的相关部分是:
try
{
...
await secondTask;
await firstTask;
}
catch(...)
{
source.Cancel();
}
现在,当第一个任务启动并抛出时,将在第二个任务之后等待它。在等待任务之前,异常不会出现在调用方中。因此,catch子句将仅在secondTask完成后执行。Cancel()发生得太晚了
如果你想让第一个任务打断第二个任务,你必须
取消是合作的:您的任务必须定期检查令牌,这需要一个循环。@HenkHolterman OP将
CancellationToken
传递给Task.Delay
。当令牌发出信号时,应该取消延迟吗?@PetSerAl-是的,我忽略了这一点。虽然文档对延迟取消的时间有点含糊不清,但我认为这里可能仍需要15秒。@Raskolnikov取消的方式不允许您预期的“订阅令牌取消事件”。。ThrowIfCancellationRequested只需检查是否请求了令牌取消,如果是,则抛出异常,如果不是,则不执行任何操作。如果在稍后阶段取消,它不会抛出。您也可以在请求取消时运行。它在两个方法的范围内,并且tr Main方法调用Cancel(),这究竟是如何回答问题的。引用:“我希望其他方法停止工作,但这不会发生”?它完全回答了这个问题。而且紧凑。通读代码。我的意思是答案太短了,如果你能添加更多关于“为什么其他方法停止工作”的解释就好了。。。也许我错了,但我不知道OP对ThrowIfCancellationRequested的看法,我不知道OP对ThrowIfCancellationRequested的看法,这其实并不重要。如何使用Parallel.Invoke
和async
方法?