2

我正在使用 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 中,但在我的一生中,我在我的代码中看不到任何共享状态。有没有人有任何想法?

谢谢,埃里克

4

1 回答 1

2

我终于找到了问题。问题是 HttpClient 发出它自己的附加任务,所以我开始的单个任务实际上可能会产生 5 个或更多任务。

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

故事的寓意:

  1. 任务可能是全局资源
  2. 任务之间通常存在不明显的相互依赖关系
  3. 调度程序不容易使用
  4. 不要假设您控制调度程序或任务数量

我最终使用了另一种方法来限制连接数。

埃里克

于 2013-04-16T19:20:34.670 回答