【问题标题】:Transforming async lambda only throwing an OperationCanceledException to synchronous variant转换异步 lambda 仅将 OperationCanceledException 抛出到同步变体
【发布时间】:2023-01-12 18:23:50
【问题描述】:

我在.NET 6 进行了这个小测试,效果很好(它是绿色的)。

Func<CancellationToken, Task> taskFactory = async token => throw new OperationCanceledException();
Assert.True(taskFactory(CancellationToken.None).IsCanceled);

然而,编译器(理所当然?)抱怨:warning CS1998: This async method lacks 'await' operators and will run synchronously。我想不出将其转换为同步变体的方法。 我为 lambda 尝试了这两个选项

  1. 没有异步:token =&gt; throw new OperationCanceledException()。我很清楚,这只会将异常直接抛出到堆栈上,而不是将其包装在任务中,但这是 IDE 的建议。
  2. token =&gt; Task.FromException(new OperationCanceledException())。这转到IsFaulted而不是IsCanceled

    将其转换为同步变体的正确方法是什么?

【问题讨论】:

    标签: c# task-parallel-library


    【解决方案1】:

    您可以使用 Task.FromCanceled 方法:

    Func<CancellationToken, Task> taskFactory = token => Task.FromCanceled(token);
    

    【讨论】:

    • 测试不是绿色的,它也离抛出异常很远
    【解决方案2】:

    您可以等待完成的任务:

    Func<CancellationToken, Task> taskFactory = async token =>
    {
        await Task.CompletedTask;
        throw new OperationCanceledException();
    };
            
    Assert.True(taskFactory(CancellationToken.None).IsCanceled);
    

    但是,您的测试确实存在竞争条件,尽管它通常很可能会成功。但是如果你把它改成这样:

    Func<CancellationToken, Task> taskFactory = async token =>
    {
        await Task.Delay(1000);
        throw new OperationCanceledException();
    };
    
    var task = taskFactory(CancellationToken.None);
    Console.WriteLine(task.IsCanceled);
    

    它将打印false。要解决这个问题,您必须等待任务完成:

    Func<CancellationToken, Task> taskFactory = async token =>
    {
        await Task.Delay(1000);
        throw new OperationCanceledException();
    };
    
    var task = taskFactory(CancellationToken.None);
    Task.WaitAny(task);
    Console.WriteLine(task.IsCanceled);
    

    请注意,我正在使用 Task.WaitAny() 等待任务完成没有TaskCanceledException。如果您只是await task;,它当然会抛出该异常。

    【讨论】:

      猜你喜欢
      • 2021-06-02
      • 2011-09-07
      • 2015-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-19
      • 1970-01-01
      相关资源
      最近更新 更多