为什么这个代码在通过TPL / Tasks执行时会失败?

时间:2012-10-22 18:56:14

标签: c# .net asp.net-web-api task-parallel-library .net-4.5

我正在使用System.Net.Http来使用网络资源。在单个线程上运行时,它可以完美运行。当我通过TPL运行代码时,它会挂起并永远不会完成,直到达到超时。

所发生的是所有线程最终都在sendTask.Result行上等待。我不确定他们在等什么,但我认为它是HttpClient中的东西。

网络代码是:

using (var request = new HttpRequestMessage(HttpMethod.Get, "http://google.com/"))
{
    using (var client = new HttpClient())
    {
        var sendTask = client.SendAsync
              (request, HttpCompletionOption.ResponseHeadersRead);
        using (var response = sendTask.Result)
        {
            var streamTask = response.Content.ReadAsStreamAsync();
            using (var stream = streamTask.Result)
            {
                // problem occurs in line above
            }
        }
    }
}

我使用的TPL代码如下。 Do方法完全包含上面的代码。

var taskEnumerables = Enumerable.Range(0, 100);
var tasks = taskEnumerables.Select
            (x => Task.Factory.StartNew(() => _Do(ref count))).ToArray();
Task.WaitAll(tasks);

我已经尝试了几种不同的调度程序,我可以让它工作的唯一方法是编写一个调度程序,将运行任务的数量限制为2或3.但是,有时甚至会失败。

我认为我的问题出现在HttpClient中,但对于我的生活,我在代码中看不到任何共享状态。有没有人有任何想法?

谢谢, 埃里克

1 个答案:

答案 0 :(得分:2)

我终于找到了这个问题。问题在于HttpClient发布了自己的附加任务,因此我启动的单个任务实际上可能会产生5个或更多任务。

调度程序配置了对任务数量的限制。我启动了任务,导致运行任务的数量达到最大限制。然后HttpClient尝试启动自己的任务,但由于达到了限制,它会阻塞,直到任务数量下降,当然从未发生过,因为他们正在等待我的任务完成。你好死锁。

故事的道德:

  1. 任务可能是全局资源
  2. 任务之间通常存在非明显的相互依赖性
  3. 调度程序不易使用
  4. 不要假设您控制调度程序或任务数量
  5. 我最终使用另一种方法来限制连接数。

    埃里克