c# - 如果已经在单独的线程上,是否有必要使用异步开始/结束方法?

标签 c# multithreading tcp

试图弄清楚我是否应该使用异步方法,例如:

相对于它们的同步 TcpListener.AcceptTcpClientNetworkStream.Read 版本。我一直在查看相关主题,但我对一件事仍然有点不确定:

问题:使用异步方法的主要优点是 GUI 不会被锁定。但是,这些方法将在单独的 Task 上调用。线程,所以没有威胁。此外,TcpListener.AcceptTcpClient 会阻塞线程,直到建立连接,这样就不会浪费 CPU 周期。既然如此,那为什么那么多人总是推荐使用异步版本呢?似乎在这种情况下,同步版本会更好?

此外,使用异步方法的另一个缺点是增加了复杂性和不断转换对象。例如,必须这样做:

private void SomeMethod()
{
    // ...

    listener.BeginAcceptTcpClient(OnAcceptConnection, listener);
}

private void OnAcceptConnection(IAsyncResult asyn)
{
    TcpListener listener = (TcpListener)asyn.AsyncState;

    TcpClient client = listener.EndAcceptTcpClient(asyn);
}

与此相反:

TcpClient client = listener.AcceptTcpClient();

另外,由于必须创建另一个线程,异步版本似乎会有更多的开销。 (基本上,每个连接都会有一个线程,然后在读取该线程时也会有另一个线程。Threadception!)

此外,还有 TcpListener 的装箱和拆箱以及与创建、管理和关闭这些额外线程相关的开销。

基本上,通常只有单独的线程来处理单独的客户端连接,现在有一个线程,然后为执行的每种类型的操作(读/写流数据和监听服务器端的新连接)创建一个额外的线程

如有错误请指正。我对线程仍然是新手,我正在努力理解这一切。但是,在这种情况下,似乎使用普通的同步方法并仅阻塞线程才是最佳解决方案?

最佳答案

TcpListener.AcceptTcpClient blocks the thread until a connection is made so there is no wasted CPU cycles.

但也没有完成任何工作。 Thread 是一个非常昂贵的操作系统对象,几乎是最昂贵的。当线程在连接请求时阻塞时,您的程序正在消耗 1 兆字节的内存而没有使用它。

However, these methods will be called on separate Task threads as it is so there is no threat of that

Task 也不是一个好的解决方案,它使用线程池线程但线程会阻塞。线程池管理器试图保持运行的 TP 线程数等于机器上的 cpu 内核数。当 TP 线程长时间阻塞时,这将无法正常工作。它会阻止其他等待轮到它们的 TP 线程完成其他有用的工作。

BeginAcceptTcpClient() 使用所谓的 I/O 完成回调。套接字监听时不会消耗系统资源。一旦连接请求进来,操作系统就会运行一个 APC(异步过程调用),它会捕获一个线程池线程进行回调。线程本身的使用时间通常为几微秒。非常有效。

在下一个 asyncawait 关键字的下一个 C# 版本中,这种代码将变得更加简单。也许是年底。

关于c# - 如果已经在单独的线程上,是否有必要使用异步开始/结束方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7477596/

相关文章:

c# - Entity Framework 中的数据库错误处理

c# - 使用互操作在 Excel 工作簿中写入长文本会引发错误?

c# - 方法调用中的分配不好的做法?

java - 在 Java EE 7 应用程序中使用 ThreadPoolExecutor 的 Drools 导致重新部署时出现问题

c++ - QTcpSocket : Setting LowDelayOption seems to have no effect?

http - 协议(protocol)不可知服务器的架构设计

c# - 来自 Swagger 和 CaSTLeWindsor 的 Azure 运行时错误

python - UDP 服务器线程化

c++ - C++11 互斥锁是否与不是用 C++11 创建的线程兼容?

c++ - 如何在 TCP/IP 中为消息长度添加前缀