【问题标题】:How to create a custom thread pool如何创建自定义线程池
【发布时间】:2015-05-18 08:06:32
【问题描述】:

我正在使用带有 .NET Framework 4.5 的 C#。我正在编写一个服务器应用程序,它应该能够一次连接到任意多个客户端。所以我有一个线程会监听连接,然后它将连接发送到后台线程以进入等待消息的循环。由于可支持的客户端连接数应该非常高,因此为每个连接生成一个新线程是行不通的。相反,我需要的是一个线程池。但是,我不想使用系统线程池,因为这些线程基本上会在调用Socket.Select 时被无限期地阻塞,或者至少在它们托管的连接的生命周期内被阻塞。

所以我认为我需要一个自定义的 ThreadPool,我可以明确地将连接轮询到。如何在 C# 中实现这一点?

【问题讨论】:

  • 这里有一点 XY 问题。您有一个要求并制定了一个解决方案,并且正在询问该特定解决方案而不是问题本身。您不希望线程与不执行任何操作的单个连接相关联是正确的。线程不是轻量级对象。这个概念类似于带有调度程序的 Stackless Python 小任务。我认为新的 TPL 东西可以实现这个想法,它有线程池和“阻塞 IO”线程池的概念,可能值得研究一下,也许使用 TPL DataFlow。

标签: c# multithreading sockets


【解决方案1】:

为此使用线程毫无意义 - 这只是浪费资源。

相反,您想使用异步 I/O。现在,忽略网络所涉及的所有复杂性,基本思想是这样的:

async Task Loop()
{
    using(var client = new TcpClient())
    {
        await client.ConnectAsync(IPAddress.Loopback, 6536).ConfigureAwait(false);

        var stream = client.GetStream();

        byte[] outBuf = new byte[4096];

        // The "message loop"
        while (true)
        {
            // Asynchronously wait for the message
            var read = await stream.ReadAsync(outBuf, 0, outBuf.Length);

            // Handle the message, asynchronously send replies, whatever...
        }
    }
}

您可以为正在建立的每个连接运行此方法(使用await - 非常重要)。处理该特定套接字的线程将在每个await 上释放 - 该await 的延续将发布在线程池线程上。

结果是,在任何给定时间使用的线程数量将趋于与可用的 CPU 内核等保持平衡,而您一次可以轻松地为数千个连接提供服务。

不要使用我发布的确切代码。您需要添加大量错误处理代码等。安全可靠地处理网络非常棘手。

【讨论】:

  • 嗯.. 我还是老派 C#,所以我从来没有真正了解过异步和等待。我想我得研究一下这些。谢谢!
  • @ZacharyTurner 您可以使用旧的异步 API 完成相同的操作(它们仍然存在),但 await 更加更舒适 - 它为您提供的代码在它自己的上下文中同步运行(如果你避免共享状态,它真的就好像它只是同步运行 - 很容易使用和推理)。最重要的是,错误处理要容易得多,因为您可以使用通常的 try-catch-finally 块。
猜你喜欢
  • 1970-01-01
  • 2019-10-17
  • 2015-03-28
  • 2010-09-27
  • 1970-01-01
  • 1970-01-01
  • 2019-07-29
  • 2023-02-02
  • 1970-01-01
相关资源
最近更新 更多