仍在等待时的 RanToCompletion

RanToCompletion when still awaiting

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

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 class 使用 HttpClient 加载站点并在处置时处置它。完整代码还使用 CancellationToken 取消并使用 SemaphoreSlim 降低并行度。

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

正如我在评论中所说,您不应该明确创建 Task。我认为您需要的是:

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.