Is it safe to call NetworkStream.BeginWrite multiple times from the same stream?
I am using a TCP client in my Unity3D game and I am wondering if it is really safe or not to call NetworkStream.BeginWrite without waiting for the previous call to finish writing.
From what I understood from reading the documentation, this is safe as long as I don't make concurrent calls to BeginWrite on different threads (and Unity only has one thread for the main game loop).
For my reading, I call BeginRead immediately after connecting with an asynchronous callback in which I read incoming data from TcpClient.GetStream (), put it in a separate blocking MemoryStream (readMemoryStream) and run BeginRead again. Also, in my Update () function (on the main game thread) I check for new data in readMemoryStream, check for a hard message and unpack it (using the same lock (readMemoryStream) of course), and perform operations on game objects on based on a message from the server.
Will this approach work fine? Will BeginRead not interfere with BeginWrite? Again, I am using a reverse stream to read data and a main stream to write.
source to share
As long as the two threads do not call BeginWrite()
at the same time, everything is fine. The same thread, or even other threads, can be called BeginWrite()
sequentially until previous calls have completed.
Note that completion callbacks may not be executed in order; if you implement it this way, and the order in which the completion callbacks are executed does matter, you have to keep track of which asynchronous operation is that. Of course, for writing to a socket, this is often irrelevant, since you cannot do anything in the completion callback other than calling EndWrite()
.
Reading and writing to a socket are completely independent operations. The socket is full duplex and can safely handle pending read and write operations on the same socket.
You didn't ask, but like BeginWrite()
, you can also call BeginRead()
multiple times without completing previous operations. Again, as with BeginWrite()
you, you need to make sure that the order of the operations is correct so that when you execute the completion callback for each of them, you know in what order the received data should be received.
Note that because the order of completion is critical for reads (which is often not the case for writes), it is common for all but the largest-scale implementations not to overlap reads on a given socket. The code is much simpler if there is only one read operation at a time on a given socket.
One final caveat: note that your buffers are tied to the duration of the I / O operation. Too many outstanding IOs can interfere with efficient heap management due to fragmentation. This is unlikely to be a problem in a client implementation, but to implement a large-scale server version, consider this (for example, allocating large buffers to come from the LOH, where they are always bound anyway).
source to share