【问题标题】:Task.WaitAll with CancelationTokenTask.WaitAll 与 CancellationToken
【发布时间】:2018-09-03 00:53:44
【问题描述】:

我需要同时执行许多方法并将所有方法的结果连接到一个列表中。在下面的示例中,我为每种方法等待 3 秒,但在其中一个方法中,我添加了一个睡眠(10 秒)来检查结果,它不是预期的。该方法永远不会取消并等待这 10 秒。问题是什么?谢谢!

var result = await Task.Run(() => Load<MyCustomClass>(OneMethod(), OtherMethod()));

private List<T> OneMethod()
{
    return new List<T>();
}

private List<T> OtherMethod()
{
    Thread.Sleep(10000);

    return new List<T>();
}

private async Task<List<T>> Load<T>(params List<T>[] taskList)
{
    try
    {
        return (await Task.WhenAll(taskList.Select(x =>
            Task.Run(() => x, new CancellationTokenSource(3000).Token)))).SelectMany(x => x).ToList();
    }
    catch (Exception currentException)
    {
        //BLA BLA BLA
    }

    return new List<T>();
}

【问题讨论】:

  • 您正在使用Thread.Sleep(),而您应该使用基于任务的等效项Task.Delay()
  • 可以去掉第一个await Task.Run(() =&gt; Load..await Load..
  • @AndrewWilliamson 嗨,感谢您的帮助。但我有同样的结果。我添加了 30 秒的延迟,但它一直在发生。
  • @Max 您好,感谢您的帮助。但我有同样的结果。
  • 为什么是Task.Run

标签: c# wpf asynchronous async-await


【解决方案1】:

您必须将CancellationToken 传递给方法并检查是否请求cancelToken 或直接引发异常。

var t = new CancellationTokenSource(3000).Token
var result = await Task.Run(() => Load<MyCustomClass>(OneMethod(t), OtherMethod(t)));

private List<T> OneMethod(CancellationToken t)
{
    token.ThrowIfCancellationRequested();
    return new List<T>();
}

private List<T> OtherMethod(CancellationToken t)
{
    Thread.Sleep(10000);
    token.ThrowIfCancellationRequested();
    // or you can check if cancellation is requested
    // if (token.IsCancellationRequested) ...
    return new List<T>();
}

private async Task<List<T>> Load<T>(params List<T>[] taskList)
{
    try
    {
        return (await Task.WhenAll(taskList.Select(x =>
            Task.Run(() => x)))).SelectMany(x => x).ToList();
    }
    catch (Exception currentException)
    {
        //BLA BLA BLA
    }

    return new List<T>();
}

this question

【讨论】:

  • Max, OtherMethod 仍然会阻塞 10 秒,即使在 3 秒后请求取消也是如此。您可以使方法异步,并将其更改为await Task.Delay(10000, t)。这样,它会在 3 秒后按预期抛出取消异常
  • @pere57 是的,它仍然不起作用,你能举个例子说明如何使它起作用吗?谢谢!
  • 为什么是Task.Run
  • 为了更好地阐明概念,我尽可能少地更改了代码。很明显真实代码中不存在延迟,需要在其他部分检查token是否过期。
猜你喜欢
  • 2022-11-15
  • 2013-09-21
  • 2016-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 1970-01-01
相关资源
最近更新 更多