Reputation: 9572
I have two methods on my Sender
class:
public void SendMessage(OutgoingMessage msg)
{
try
{
stream.BeginWrite(msg.TcpData, 0, 16, messageSentCallback, msg);
}
catch
{
// ...
}
}
private void messageSentCallback(IAsyncResult result)
{
stream.EndWrite(result);
if (result.IsCompleted)
onDataSent(result.AsyncState as OutgoingMessage);
}
Other parts of the program can call (if they have an access to the Sender) the SendMessage()
method. Since the program works in multi-threading environment, multiple threads have access to the Sender object.
I have 2 questions:
Q1) Would making two concurrent calls to the SendMessage
method be able to mess up the TCP communication (by filling the TCP outgoing buffer with mixed data)?
Q2) Would enclosing the stream.BeginWrite()
call into the lock { }
solve this problem?
As far as I understand, the call to BeginWrite simply stores the data into the TCP outgoing buffer. Is that right?
Upvotes: 3
Views: 3569
Reputation: 6626
If you would like to minimize blocking and maintain high concurrency with multiple writer threads I would recommend using the Socket.SendAsync
which accepts a SocketAsyncEventArgs
.
You could preallocate a number of SocketAsyncEventArgs (with its associated buffer space) that are used as writers, in which case, rather than having a lock you would have a SemaphoreSlim
which would allow a number of 'simultaneous' writes pushing the synching lower down the protocol stack.
Good luck!
Upvotes: 1
Reputation: 62469
Yes, a lock is required to avoid problems. However, I would switch to a different approach, both to solve concurrency problems as well as to make the thread interaction more easy to reason about.
You could have a shared queue where several threads put requests that need to be written to the stream. A single thread then reads requests from the queue and makes write operations. Now it's much easier to understand what is going on and you don't have to worry about synchronizing the writes. You could use one of the concurrent collections like ConcurrentQueue
.
Upvotes: 3
Reputation: 30127
MSDN Says
As long as there is one unique thread for the write operations and one unique thread for the read operations, there will be no cross-interference between read and write threads and no synchronization is required.
Which means that if you have more than one threads sending data then you should use lock
to make sure only one thread calls BeginWrite
at a time in order to send data without any interference
Upvotes: 1