ThreadPool 如何处理传递的变量
Posted
技术标签:
【中文标题】ThreadPool 如何处理传递的变量【英文标题】:How does a ThreadPool work with passed variables 【发布时间】:2020-09-17 05:09:13 【问题描述】:我目前正在尝试通过线程池接受传入连接,这一切正常,但提出了以下问题:
如果我在线程池处理前一个连接之前获得一个新连接怎么办。 传递给函数(在本例中为客户端)的对象是被新连接替换还是会同时记住两者?
我认为它忘记第一个客户端的原因是因为传递的变量只是一个引用,对吗?
代码如下:
public static void Initialize()
socket.Start();
System.Threading.Thread newConnection = new System.Threading.Thread(() =>
while (isOnline)
System.Net.Sockets.TcpClient client = socket.AcceptTcpClient();
System.Threading.ThreadPool.QueueUserWorkItem(HandleNewClient, client);
)
IsBackground = true,
Name = "newConnection",
Priority = System.Threading.ThreadPriority.Highest
;
我希望这对你们来说很清楚。 提前感谢您对此进行调查。
【问题讨论】:
socket
未定义为参数,因此它是类范围或静态。这通常是一个坏主意。套接字应该是可处置的,其规则是:“创建。使用。处置。全部在同一段代码中,最好使用 using 块”。我能想到的一个例外是日志文件——或者更确切地说,它们或多或少地对整个应用程序作为“使用”范围负责。
您将该函数标记为无效,这是一个潜在问题。对于各种风格的多任务处理,意外吞下异常是一个大问题。除非线程池负责捕获和公开异常,否则您将遇到问题。
Mutlithreading 似乎也太过分了,因为没有任何 CPU 限制。这可以仅通过异步来完成。那么抛出一个线程池的整个想法是没有意义的。他们有一个 shared 套接字。在一个资源上工作的多件事只会导致问题。使用线程池进行多线程似乎是一个 XY 问题。
@Christopher 首先感谢您的快速回复。其次,这是我捕获新连接并将套接字复制到他们自己的线程并从那里处理所有内容的部分。我不能让多个线程监听同一个端口接受客户端,对吗?还是使用按顺序执行的多个任务相互等待?
【参考方案1】:
我认为您基本上是在尝试重新发明 WebServer 或类似的东西。我的第一个建议是永远不要重新发明***,如果你有一辆完全加油的汽车就站在那里,钥匙在点火开关上。
尤其是网络问题已经解决了几十次。
但如果你必须自己做,通常你会得到:
一个公共端口 一个除了监听端口之外什么都不做的线程,将接收到的所有内容放入ConcurrentQueue、Channel 或类似结构中。 一个巨大的线程池。我们说的是平均 ASP.Net 服务器上每个 CPU 核心 50-100 个线程。 如果有任何事情要做,这些线程将开始查看队列。您想为每个客户端分配一个不同的端口,以保持连接分开。甚至可能尝试让 1 个线程从头到尾处理每个请求(但是,在实践中并不能保证这一点;期望负责的线程会改变)。谈判大概是这样的:
客户端到端口 80:“嘿,我想谈谈” 服务器计算并锁定一个随机的未使用端口:“好的,你可以在端口 54321 上与我交谈”。 客户端到端口 54321:“好的,这就是我想要的……”【讨论】:
我要做的是管理所有客户端连接并与网络中的多个服务器进行通信的网关。即使按照您上面描述的方式,这一切也已经完成了。一个用于开始连接的公共端口并将其重定向到一个新端口。我现在应该研究的巨型线程池我使用一个运行和管理一个客户端的类。 这篇文章中的代码是监听新客户端的线程,只是想知道如果两个客户端同时连接会发生什么。像这样,我怀疑这一切都会崩溃。但我明白这是这样做的方法。新连接转到新线程并完成端口。 @JorisdeVos “如果 2 个客户端恰好同时连接” 他们可以很快连接,但不能同时连接。在只有全双工甚至半双工的网络硬件和确保您只获得完整软件包的 Windows 网络堆栈之间,您永远不必担心这些细节。 太棒了!这就是我要找的。请将此作为答案发布并不接受。再次感谢。以上是关于ThreadPool 如何处理传递的变量的主要内容,如果未能解决你的问题,请参考以下文章