Task.FromCanceled的目的是什么?

3

我刚开始接触TPL,对Task类静态方法中的FromXXX方法的目的感到困惑:

public class Task : ... 
{
   public static Task FromCanceled(CancellationToken cancellationToken);
   public static Task FromException(Exception exception);
   public static Task<TResult> FromResult<TResult>(TResult result);
}

Task.FromCanceled 为例,我们为什么需要它呢?当我们创建一个 Task 时,我们希望执行一些操作,那么创建一个永远不会执行任何操作的已取消任务有什么用途呢?


1
“创建一个无法执行任何操作的已取消任务的目的是什么?”也许你会遇到需要这样做的情况?你可以对FromException提出同样的问题。 - ProgrammingLlama
4
最简单的使用情况:您正在设计一个单元测试,以验证当请求的任务被取消时,某些代码的行为是否正确。 - Franz Gleichmann
1
可能是因为您需要实现一些异步接口方法,但实际上您并不需要等待任何东西。 - Jeremy Lakeman
请查看 不要问 以了解您应避免提出哪些问题。这个问题是一个没有重点的开放式假设性问题,因此会有许多同样有效的答案。 - Brett Caswell
2个回答

6

以下是一个示例。您有一个库,声明了一个返回 Task 的方法,并考虑使用 async/await

public interface IFoo
{
    Task BarAsync(CancellationToken token);
}

但你的代码 / 单元测试方法是同步的,没有需要等待的内容,因此我们可以使用 Task.FromResult 等方式来实现它。

public class MyFoo : IFoo
{
    public Task BarAsync(CancellationToken cancellationToken)
    {
        if (cancellationToken.IsCancellationRequested)
        {
            return Task.FromCanceled(cancellationToken);
        }
        return Task.CompletedTask;
    }
}

请注意,你也可以在实际场景中找到类似的示例。可通过GitHub搜索来查找。
例如,这个代码在一个与上述描述类似的场景中使用它。

2

这里有一个例子。

假设我有一个需要很长时间才能完成的方法,接下来还有另一个方法。如果我想取消这个过程并且不希望第二个方法运行,那么我可能需要返回一个已取消的任务。

像这样:

Task<string> query =
    from t in Task.Run(() => GetLongRunningValue())
    from x in cts.IsCancellationRequested
        ? Task.FromCanceled<string>(cts.Token) 
        : Task.Run(() => t + "!")
    select x;

这是让你能够使用LINQ和任务的代码:

以下是需要翻译的内容:

public static class TaskEx
{
    public static Task<R> Select<T, R>(this Task<T> task, Func<T, R> s) => task.ContinueWith(t => s(t.Result));
    public static async Task<R> SelectMany<T, R>(this Task<T> task, Func<T, Task<R>> k) => await k(await task);
    public static async Task<R> SelectMany<T, U, R>(this Task<T> task, Func<T, Task<U>> k, Func<T, U, R> s)
    {
        var t = await task;
        var u = await k(t);
        return s(t, u);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接