【问题标题】:RanToCompletion when still awaitingRanToCompletion 仍在等待时
【发布时间】:2017-09-01 08:22:51
【问题描述】:

我需要编写一个异步加载和解析多个网站的方法。 这是我的方法的简化代码。

using (HTMLParser parser = new HTMLParser(proxy))
{
    var tasks = totalSites.Select( s =>
    {
        return new Task( async () =>
        {
            s.Entity = await parser.GetSiteDataAsync(s.Entity).ConfigureAwait(false);
        });
    }).ToArray();
    foreach (var task in tasks)
        task.Start();
    await Task.WhenAll(tasks).ConfigureAwait(false);
}

HTMLParser 类使用HttpClient 加载站点并在处置时处置它。完整代码还使用CancellationToken 取消并使用SemaphoreSlim 降低并行度。

问题是当任务开始等待解析数据时,它的状态设置为RanToCompletion。然后程序通过Task.WhenAll 并处理HTMLParser 导致OperationCanceledExceptions 在HttpClient

【问题讨论】:

  • 如果您的代码将受 I/O 限制,那么您的方法通常不应显式创建新的 Task 对象。我认为您当前的代码以 Tasks 包装其他 Tasks 结尾,这并不大。
  • @GWigWam ,对不起,我错过了简化我的代码。 s 用于创建vm。 @Damien_The_Unbeliever 我认为你是对的:我需要创建多个任务来并行加载多个网站。
  • @AndreyAlonzov - 但对于 I/O 绑定工作,您不应该创建 Tasks - 您应该利用 asyncawait 但只有Tasks 你应该处理的是那些由async 方法返回的。
  • @Damien_The_Unbeliever 如果我将使用该任务,我如何一次加载 40 个网站。

标签: c# asynchronous async-await task-parallel-library dotnet-httpclient


【解决方案1】:

就像我在 cmets 中所说,您不应该明确创建 Tasks。我认为您需要的是以下内容:

using (HTMLParser parser = new HTMLParser(proxy))
{
    var tasks = totalSites.Select( s => populateEntity(s)).ToArray();
    /* returned tasks are already hot */
    //foreach (var task in tasks)
    //    task.Start();
    await Task.WhenAll(tasks).ConfigureAwait(false);
}

然后分别:

public async Task<WhateverSIs> populateEntity(WhateverSIs s)
{
    s.Entity = await parser.GetSiteDataAsync(s.Entity).ConfigureAwait(false);
    return s;
}

我们不会显式创建任何Tasks - 我们只是使用通过async 方法公开的那些,包括GetSiteDataAsync

【讨论】:

  • 谢谢!只是自己做了同样的事情。昨天我尝试了这种方法,但是我在 lambda 中编写了所有逻辑并且取消不起作用并迫使我显式地创建任务。
  • @AndreyAlonzov - 异步 lambda 的问题在于它们可以轻松生成 FuncAction 代表 - 而 Action 代表实际上是 async void。如果您查看where you were passing your lambda,您会发现它只能使用Action - 所以您无法跟踪您的 lambda 的进度。
猜你喜欢
  • 2016-06-18
  • 1970-01-01
  • 2014-07-19
  • 2018-03-07
  • 2020-10-30
  • 2016-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多