如何取消 ValueTask<T>

Jos*_*osh 0 c# task-parallel-library cancellation async-await .net-core

我知道如何取消任务,但找不到有关如何向 ValueTask 方法添加取消的任何信息。通常我会取消这样的任务:

public async Task<int> Foo(
    CancellationToken cancellationToken)
{
    TaskCompletionSource<int> tcsCancel =
        new TaskCompletionSource<int>();

    cancellationToken.Register(() =>
    {
        tcsCancel.TrySetCanceled();
    });

    Task<int> task = LongOperation();

    var completedTask = await Task.WhenAny(
        tcsCancel.Task,
        task).ConfigureAwait(false);

    return await completedTask.ConfigureAwait(false);
}
Run Code Online (Sandbox Code Playgroud)

或者像这样:

if (cancellationToken.IsCancellationRequested)
    return Task.FromCanceled<int>(cancellationToken);
Run Code Online (Sandbox Code Playgroud)

事实是,ValueTask 既没有 FromCanceled 也没有 WhenAny。我是不是应该做...

cancellationToken.ThrowIfCancellationRequested();
Run Code Online (Sandbox Code Playgroud)

Ste*_*ary 5

您所指的那种“取消”并不是真正的取消;而是真正的取消。您取消的是等待,而不是操作

您可以使用 ; 进行相同类型的假取消操作ValueTask<T>;您只需将其转换Task<T>为即可:

public async ValueTask<int> Foo(CancellationToken cancellationToken)
{
  using var tcsCancel = new TaskCompletionSource<int>();
  using var registration = cancellationToken.Register(() =>
  {
    tcsCancel.TrySetCanceled();
  });

  ValueTask<int> valueTask = LongOperation();
  Task<int> task = valueTask.AsTask();
  var completedTask = await Task.WhenAny(
      tcsCancel.Task,
      task).ConfigureAwait(false);

  return await completedTask.ConfigureAwait(false);
}
Run Code Online (Sandbox Code Playgroud)

  • @Josh:套接字接收不可取消。这样想:如果您的代码确实取消了接收,那么它就无法知道套接字处于什么状态。无论 API/运行时/语言/操作系统如何,都是如此。取消任何套接字操作的唯一正确方法是关闭套接字,这会取消*所有*套接字操作。 (3认同)