说,我有一个类,包装一个Socket和(除了其他东西)执行异步数据发送。
我按以下方式执行发送(大大缩写 - 没有错误处理等):
private Socket _socket;
public void Write(byte[] data, Action callback)
{
_socket.BeginSend(
data, 0, data.Length, SocketFlags.None,
new AsyncCallback(WriteMaybeDone),
new { Data = data, SentSoFar = 0, Callback = callback}
)
}
public void WriteMaybeDone(IAsyncResult ar)
{
int bytesSent = _socket.EndSend(ar);
var state = ar.AsyncState;
state.SentSoFar += bytesSent;
if (state.SentSoFar < state.Data.Length) {
_socket.BeginSend(
data, state.SentSoFar, State.Data.Length - state.SentSoFar,
SocketFlags.None,
new AsyncCallback(WriteMaybeDone), state
);
} else {
if (state.Callback != null) {
state.Callback();
}
}
}
这里我们确保在调用传递的回调之前发送所有数据。
如何确保对Write的“重叠”调用以可预测的方式运行?特别是因为可以在发送所有数据之前调用传递给BeginSend的回调。我需要确保传递给Write的调用的数据转到与数据交错的不的数据,然后传递给后续的Write调用,这些调用是在第一次调用之前进行的。写入被解雇。
我受限于.NET 3.5
答案 0 :(得分:1)
仅在上一次完成后启动下一个发送操作。您可以将要发送的数据入队,或使用信令机制(如AsyncSemaphore
或TaskCompletionSource
)通知下一次写入前一个已完成。
换句话说,使用生产者 - 消费者设计模式。生产者是想要写作的操作。单个使用者是一个线程或异步工作流,它一个接一个地进行物理写入。