C# 取消另一个类C中的任务#

C# 取消另一个类C中的任务#,c#,task,cancellationtokensource,cancellation-token,C#,Task,Cancellationtokensource,Cancellation Token,我对C中的cancellationTokenSource有一个问题# 在中的另一个类中,我们希望检测任务是否像这样被取消,但它不起作用。中的捕获异常从未触发 public async Task<Building> GetBuildingOfUserTask() { double remainingTime = unitService.GetRemainingTime(); if (remainingTime <= 2000 &&

我对C中的cancellationTokenSource有一个问题#

在中的另一个类中,我们希望检测任务是否像这样被取消,但它不起作用。中的捕获异常从未触发

public async Task<Building> GetBuildingOfUserTask()
    {
        double remainingTime = unitService.GetRemainingTime();

        if (remainingTime <= 2000 && remainingTime > 0.0)
        {
            Building building = GetBuilding();
            CancellationToken cancellation = building.BuildTokenSource.Token;
            try
            {
                await buildTask;
            }
            catch (OperationCanceledException) when (cancellation.IsCancellationRequested)
            {
                return GetBuildingOfUser();
            }
        }
        return GetBuildingOfUser();
    }
公共异步任务GetBuildingFuserTask() { double remainingTime=unitService.GetRemainingTime(); 如果(剩余时间0.0) { Building=GetBuilding(); CancellationToken cancellation=building.BuildTokenSource.Token; 尝试 { 等待任务; } 捕获(OperationCanceledException)时(cancellation.IsCancellationRequested) { 返回getBuildingFuser(); } } 返回getBuildingFuser(); }
有人知道这为什么不起作用,在本例中有解决方案吗?

我没有看到任何地方调用
cancelbuild()
+您必须调用
BuildTokenSource.Token.throwifccancellationrequested()
才能引发
操作取消异常

应在使用cancelationToken的异步方法外部调用
令牌.Cancel()
。另外,使用异步方法必须调用(通常在每个步骤中)
Token.throwifcancellationrequest()

我认为使用中介()会更合适。这实际上是一个发布子模型,它将在取消时发布一个事件,并通知所有订阅者

第一个类将中介实例作为引用(只读字段、属性)来发布cancel事件,另一个类应将相同的实例作为引用,以便在事件实际发生时得到通知。您应该采取的另一点是,当包含“GetBuildingFuserTask”方法的类的实例被销毁时,应该取消订阅

你怎么看?

时钟延迟(构建时间)
是否有接受
取消令牌的重载?如果是的话,就用这个


问题是,如果代码已经在等待clock.Delay(Build_TIME)
取消时,
clock.Delay
将不知道它需要抛出异常。

我同意Hadascoky的答案,我想带来更多的启示

您有一个主任务启动于
任务构建服务.buildTask
,而它的从属任务启动于
等待时钟.Delay(构建时间)

第一个任务管理
CancellationToken
,但从属任务不管理。为了更好地理解它,请将
时钟延迟(构建时间)
替换为
任务延迟(int毫秒延迟,取消令牌取消令牌)
并提供
CancelationToken
。您将看到,在这种情况下,从属任务将被取消。同时调用void CancellationToken.CancelAfter(int毫秒延迟)

由于您未向已启动主任务的从属任务提供
CancellationToken
,因此不会取消主任务及其从属任务

另一方面,要在执行从属任务时取消,请向从属任务提供一些逻辑,以将
CancelationToken
管理到其相应的方法中,并在必要时调用
CancelationToken.throwifccancellationrequested()
,从而抛出
OperationCanceledException

至少,试着把长任务分成几个小任务。
我用来管理异步。任务,这些任务必须按顺序运行到一个任务队列中,该队列能够观察这些
任务状态
。为了解决这个问题,如果您需要,我在github上有一个实现。我称之为“它不起作用”什么不起作用?编译器错误?例外?行为与预期不同?任务未取消。捕获异常从不触发或重新关联:
public async Task<Building> GetBuildingOfUserTask()
    {
        double remainingTime = unitService.GetRemainingTime();

        if (remainingTime <= 2000 && remainingTime > 0.0)
        {
            Building building = GetBuilding();
            CancellationToken cancellation = building.BuildTokenSource.Token;
            try
            {
                await buildTask;
            }
            catch (OperationCanceledException) when (cancellation.IsCancellationRequested)
            {
                return GetBuildingOfUser();
            }
        }
        return GetBuildingOfUser();
    }