对于 C# 中的多客户端 TCP 服务器,如何在线程之间划分工作?

How to Divide Work bewteen Threads, for a MultiClient TCP Server in C#?

在 C# 中创建多客户端服务器时,我可以想到几种 方法来划分线程之间的工作。

对于这个问题,假设服务器接受来自客户端的传入 TCP 连接,并且每个客户端都为服务器发送一个文件,以存储在硬盘上。

工作部门1: 每个客户的线程: 服务器将为每个连接的新客户端实例化一个新线程, 该线程将负责该客户。 (那些线程,除了 1 "server thread")

工作部门二: 每个资源的线程: 将有 1 个线程用于处理通信, 和 1 个用于写入硬盘的线程。 客户端对象将在这些资源负责线程中的每一个之间传递,并且每个资源负责线程都有自己的队列,因此它可以知道自己应该做什么。 (同样,这些线程是 1 "server thread" 的补充)

工作分部3: 主任务的每个子任务的线程: 让我们将每个连接客户端需要完成的工作称为 "the main task"。 所以我们将把这个主要任务分解成几个子任务, 并为每个子任务创建一个线程, 同样,每个线程都会有一个队列来保存它应该处理的客户端项目。 (这听起来很像二区,但在另一个工作不同的项目而不是文件接收服务器中,这种类型的区可能与二区有很大不同)

我的问题是:

是否有其他建议的方法来划分线程之间的工作?

答案是除非连接的客户端很少,否则您根本不使用线程。原因是线程会带来开销,并且线程将在大部分时间处于空闲状态,因为您使用的是慢速资源 (IO)。

相反,您应该看看异步编程。在 dotnet 中你有三个模型:

  • APM(异步编程模型)
  • 基于事件的异步模式 (EAP)
  • 基于任务的异步模式 (TAP)

https://msdn.microsoft.com/en-us/library/jj152938(v=vs.110).aspx

APM 是最早的一个。我只在您的 dotnet 版本不支持 EAP 或 TAP 时才推荐它。但在您的情况下,您需要使用 APM (.NET 2.0),并且可以在此处阅读更多相关信息:https://msdn.microsoft.com/en-us/library/ms228963(v=vs.110).aspx

当您使用异步编程时,您不必再担心线程。 .NET 和 OS 将管理线程。您的应用程序将 "awake" 在您订购的 IO 操作中完成某些操作(例如通过套接字发送某些内容或从数据库中读取)。

I would like to implement, whichever solution chosen, using the Thread class, and not using other classes/tools from the .NET framework.

只有#1 可行。写入磁盘将比通过网络接收文件更快。所以真的没有理由让资源拥有线程。

使用#1 也会降低复杂性并使代码更易于阅读。您仍然需要一项服务来确保两个客户端不会使用同一个文件。