我正在构建相当复杂的并发系统,偶然发现了一个奇怪的问题。我会尽量简单。
- 我在.net core 2.1上有一个单实例控制台应用程序
- 我有一个HttpClient实例
- 我设置了以下参数:
System.Net.ServicePointManager.DefaultConnectionLimit = int.MaxValue;
System.Net.ServicePointManager.ReusePort = true; HttpClient.DefaultRequestHeaders.ConnectionClose = true;
HttpClient.SetBearerToken(SOME_TOKEN);
- 我有一个线程(A),该线程使用 ThreadPool / new Thread()在内部使用单个HTTP GET查询不断创建多达30个新的并发线程(都尝试了),然后将结果放入ConcurrentQueue变量中。
- 我还有另一个线程(B),该线程从队列中读取数据,并通过内部一个HTTP POST查询不断创建多达30个新的并发线程。
问题是我遵循以下工作流程:
- A线程运行良好,将结果与队列一起馈入。所有线程运行正常。
- 在A线程启动之后,B线程开始为POST创建子线程。
- A线程完成其工作,所有线程均已完成。此时,由B线程创建的所有线程都挂在 await client.PostAsync()方法上。
- 应用程序挂起约10秒钟。
- VS日志显示多个线程0x35e0已退出,代码为0(0x0)。消息提示先前使用的线程正在释放。为什么这么久?!
- 应用程序会暂停20秒
- 由B线程创建的第一个线程开始失败,然后所有其他B线程开始正常执行。
尝试:
-
一次将并发线程数减少到5-10可解决问题,但完全破坏了并发性能。
-
我看到日志中的线程计数并且没有溢出,A和B一次最多30个线程(最多大约60个线程)
-
试图降低 System.Net.ServicePointManager.DefaultConnectionLimit 参数,但无济于事。
看起来有些东西阻止了POST查询,然后它们又正常地再次着急。请就此问题提出建议。谢谢。
PS:我处理 Flickr 查询。可能是他们的某些访问限制吗?无论如何,POST挂起看起来都很奇怪,只是挂起而没有单次通过。