C#async CTP - 如何在不抛出TaskCanceledException的情况下将异步任务标记为已取消?

Mik*_*ike 6 c# cancellation async-ctp

我有一个简短的异步任务,它经常需要在启动后取消."Task"类有一个IsCanceled指示器,我认为可以方便地指示异步任务在没有运行完成的情况下被取消,但据我所知,将异步任务标记为已取消的唯一方法是在异步函数中抛出TaskCanceledException.例行地抛出异常,以指示无异常发生的情况,违背了我应该如何理解应该使用的异常.是否有人知道更好的方法来指示异常任务在预计经常发生时被取消?

我的下一个最好的选择是返回一个拥有它自己的IsCanceled属性的结构:

(为了简洁,我忽略了一些好的编码和样式实践)

class MightBeCanceled<T>
{
    public readonly T Value;
    public readonly bool IsCanceled;

    public MightBeCanceled(T value) { Value = value; IsCanceled = false; }
    public static MightBeCanceled<T> Canceled = new MightBeCanceled<T>(default(T), true);
    private MightBeCanceled(T value, bool isCanceled) { Value = value; IsCanceled = isCanceled; }
}

...

static async Task<MightBeCanceled<int>> Foo()
{
    if (someCancellationCondition)
        return MightBeCanceled<int>.Canceled;
    else
        return new MightBeCanceled<int>(42);
}

static async void Bar() 
{
    var mightBeCanceled = await Foo();

    if (mightBeCanceled.IsCanceled)
        ; // Take canceled action
    else
        ; // Take normal action
}
Run Code Online (Sandbox Code Playgroud)

但这似乎是多余的,更难以使用.更不用说它引入了一致性问题,因为会有两个IsCanceled(一个在Task中,一个在MightBeCanceled中).

Tej*_*ejs 2

问题是,在您选择等待之前,异常将不会被观察到。因此,调用行为await意味着当返回最终值或等待任务完成时,您最终将在某个时刻观察到异常。但是,如果您从不关心(这是一个即发即忘的任务),那么例外就不是问题(在大多数情况下)。

我也觉得这有点奇怪,总是必须尝试/捕获任务来处理聚合异常。不过,稍微想一下:

 try
 {
     var myResult = await Foo();

     // Do Success Actions Here... 
 }
 catch(AggregateException e)
 {
     e.Flatten().Handle(ex =>
       {
           if(ex is OperationCanceledException)
           {
               // Do Canceled Thing Here
               return true;
           }

           return false;
       });
 }
Run Code Online (Sandbox Code Playgroud)

距离并不遥远。在很多方面,我都想取消另一项任务,我该怎么做?ThreadAbortException?在取消时简单地抛出特定异常似乎并不牵强。

这几乎是我在多个地方看到的关于如何处理取消的主张的模式。