【问题标题】:How to cancel ValueTask<T>如何取消 ValueTask<T>
【发布时间】:2020-04-07 00:24:22
【问题描述】:

我知道如何取消任务,但找不到任何有关如何将取消添加到 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);
}

或者像这样:

if (cancellationToken.IsCancellationRequested)
    return Task.FromCanceled<int>(cancellationToken);

问题是,ValueTask 既没有 FromCanceled 也没有 WhenAny。我应该这样做吗...

cancellationToken.ThrowIfCancellationRequested();

【问题讨论】:

  • 为什么不将取消令牌传递给LongOperation();?你在做什么似乎很奇怪,我不相信它会取消 LongOperation(); 以至于忽略它的结果。
  • 别管逻辑了。我刚刚意识到我犯了一些错误。但总的来说,我仍然想知道如何使用 ValueTask 添加取消支持

标签: c# .net-core async-await task-parallel-library cancellation


【解决方案1】:

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

你可以用ValueTask&lt;T&gt;做同样的假取消;您只需要将其转换为 Task&lt;T&gt; 即可:

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);
}

【讨论】:

  • 谢谢斯蒂芬!我需要伪造取消的原因是因为 SocketTaskExtensions.ReceiveAsync 不支持取消。但我刚刚意识到他们添加了一个带有 CancellationToken 的 ValueTask 的重载。您是否知道此 CancallationToken 是否正确取消了 ReceiveAsync?还是也只是假取消?我找不到此方法的任何参考或源代码来验证。
  • 没有办法真正取消 IO 操作,除非驱动程序支持。取消一个 IO 操作意味着忽略它的结果。
  • @Josh:套接字接收不可取消。这样想:如果您的代码确实取消了接收,那么它就无法知道套接字处于什么状态。无论 API/运行时/语言/操作系统如何,这都是正确的。取消任何套接字操作的唯一正确方法是关闭套接字,这会取消 所有 套接字操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-14
  • 2019-02-24
  • 2021-10-31
  • 2017-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多