为什么此代码在通过 TPL/Tasks 执行时会失败? [英] Why does this code fail when executed via TPL/Tasks?

查看:19
本文介绍了为什么此代码在通过 TPL/Tasks 执行时会失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using System.Net.Http to use network resources. When running on a single thread it works perfectly. When I run the code via TPL, it hangs and never completes until the timeout is hit.

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

What happens is that all the threads end up waiting on the sendTask.Result line. I am not sure what they are waiting on, but I assume it is something in 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 方法完全包含上面的代码.

The TPL code that I am using is as follows. The Do method contains exactly the code above.

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

我尝试了几个不同的调度程序,唯一能让它工作的方法是编写一个调度程序,将运行任务的数量限制为 2 或 3.但是,即使这样有时也会失败.

I have tried a couple of different schedulers, and the only way that I can get it to work is to write a scheduler that limits the number of running tasks to 2 or 3. However, even this fails sometimes.

我认为我的问题出在 HttpClient 中,但在我的一生中,我在我的代码中看不到任何共享状态.有人有什么想法吗?

I would assume that my problem is in HttpClient, but for the life of me I can't see any shared state in my code. Does anyone have any ideas?

谢谢,埃里克

推荐答案

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

I finally found the issue. The problem was that HttpClient issues its own additional tasks, so a single task that I start might actually end spawning 5 or more tasks.

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

The scheduler was configured with a limit on the number of tasks. I started the task, which caused the number of running tasks to hit the max limit. The HttpClient then attempted to start its own tasks, but because the limit was reached, it blocked until the number of tasks went down, which of course never happened, as they were waiting for my tasks to finish. Hello deadlock.

故事的道德:

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

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

I ended up using another method to throttle the number of connections.

埃里克

这篇关于为什么此代码在通过 TPL/Tasks 执行时会失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆