【问题标题】:Is safe to call NetworkStream.BeginWrite multiple times from one thread?从一个线程多次调用 NetworkStream.BeginWrite 是否安全?
【发布时间】:2015-06-05 12:51:04
【问题描述】:

我正在我的 Unity3D 游戏中实现一个 TCP 客户端,我想知道在不等到前一个调用完成写入的情况下调用 NetworkStream.BeginWrite 是否真的安全。

根据我在阅读文档时的理解,在我不在不同线程中执行并发 BeginWrite 调用之前是安全的(并且 Unity 只有一个线程用于游戏主循环)。

对于我的阅读,我在与异步回调建立连接后立即调用 BeginRead,在异步回调中,我从 TcpClient.GetStream() 读取传入数据,将其放入带有 lock(readMemoryStream) 的单独 MemoryStream,然后再次运行 BeginRead。除此之外,在我的 Update() 函数中(在主游戏线程中)我检查 readMemoryStream 中的新数据,检查可靠消息并将其解包(当然使用相同的锁(readMemoryStream))并在基于来自服务器的消息的游戏对象。

这种方法行得通吗? BeginRead 不会干扰 BeginWrite 吗? 再次,我使用回调线程读取数据和主线程写入。

【问题讨论】:

    标签: c# unity3d mono tcpclient


    【解决方案1】:

    只要没有两个线程同时调用BeginWrite(),一切都很好。同一个线程,甚至其他线程,可以在之前的调用完成之前连续调用BeginWrite()

    请注意,完成回调可能会乱序执行;如果您确实以这种方式实现它并且完成回调的执行顺序很重要,则由您来跟踪哪个异步操作是哪个。当然,对于写入套接字,这通常无关紧要,因为您可能在完成回调中除了调用 EndWrite() 之外没有任何事情可做。

    读取和写入套接字是完全独立的操作。套接字是全双工的,可以安全地处理同一个套接字上同时挂起的读写操作。


    你没有问,但像BeginWrite(),你也可以多次调用BeginRead(),而不需要完成之前的操作。同样,与BeginWrite() 一样,由您来跟踪操作的正确顺序,以便在为每个操作执行完成回调时,您知道接收数据的顺序。

    请注意,由于完成的顺序对于读取操作至关重要(写入操作通常不是这种情况),除了最大规模的实现之外,所有实现都不会在给定套接字上重叠读取操作是很常见的。对于给定的套接字,代码更简单,一次只进行一个读取操作。


    最后一个警告:请注意,您的缓冲区在 I/O 操作期间是固定的。由于碎片,太多未完成的 I/O 操作会干扰堆的有效管理。这在客户端实现中不太可能成为问题,但大规模服务器实现应该考虑到这一点(例如,通过分配大缓冲区,以便它们来自 LOH,无论如何总是固定的东西)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-15
      • 1970-01-01
      • 2018-06-30
      • 1970-01-01
      • 2017-07-15
      • 1970-01-01
      相关资源
      最近更新 更多