RanToCompletion还在等待

时间:2017-09-01 08:22:51

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

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

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加载网站并将其置于dispose上。完整代码还使用CancellationToken取消,SemaphoreSlim以降低并行度。

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

1 个答案:

答案 0 :(得分:4)

就像我在评论中所说,你不应该明确地创建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