我的Sender
课程有两种方法:
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);
}
程序的其他部分可以调用(如果他们可以访问发件人)SendMessage()
方法。由于程序在多线程环境中工作,因此多个线程可以访问Sender对象。
我有 2个问题:
Q1)对SendMessage
方法进行两次并发调用是否能够搞乱TCP通信(通过使用混合数据填充TCP传出缓冲区)?
Q2)将stream.BeginWrite()
电话括在lock { }
中解决此问题?
据我所知,对BeginWrite的调用只是将数据存储到TCP传出缓冲区中。是吗?
答案 0 :(得分:3)
是的,需要锁定才能避免问题。但是,我会切换到另一种方法,既解决并发问题,又使线程交互更容易推理。
您可以拥有一个共享队列,其中多个线程将需要写入的请求写入流。然后,单个线程从队列中读取请求并进行写入操作。现在,更容易理解正在发生的事情,您不必担心同步写入。您可以使用其中一个并发集合,例如ConcurrentQueue
。
答案 1 :(得分:2)
只要有一个唯一的写操作线程和一个 用于读取操作的唯一线程,将没有 读写线程之间的交叉干扰没有 同步是必需的。
这意味着如果您有多个线程发送数据,那么您应该使用lock
来确保一次只有一个线程调用BeginWrite
以便发送数据而不会受到任何干扰
答案 2 :(得分:1)
如果您希望最小化阻塞并使用多个编写器线程保持高并发性,我建议使用接受Socket.SendAsync
的SocketAsyncEventArgs
。
你可以预先分配一些用作编写器的SocketAsyncEventArgs(及其相关的缓冲区空间),在这种情况下,你可以拥有SemaphoreSlim
而不是锁定,这将允许一些“同时”写入推送同步降低协议栈。