我想使用Socket
將實時數據從一臺服務器廣播到多臺客戶機。
但是,我遇到了當前實現中的併發問題。通過套接字流式傳輸數據
public class Connection {
private volatile bool readyToSend;
private Queue<byte[]> q;
private object bufferMonitor;
public Connection {
// initialize all things etc and connect
}
[...] // some other functions which are irrelevant for this problem
private void ClientConnected (SocketAsyncEventArgs args) {
// called by Thread A
[...]
readyToSend = true;
WaitingForResponse(args);
}
private void WaitingForResponse (SocketAsyncEventArgs) {
// called by Thread A
if (q.Count == 0) {
lock (bufferMonitor) {
Monitor.Wait(bufferMonitor);
}
}
if (q.Count != 0) {
byte[] data;
lock (q) {
data = q.Dequeue();
}
args.SetBuffer(0, data.Length);
args.ConnectSocket.SendAsync(args);
// Will send all bytes and recall to WaitingForResponse afterwards
} else {
// Will recall this function if nothing happened.
}
}
internal void SendIfConnected (byte[] data) {
// called by Thread B
if (readyToSend) {
lock (q) {
q.Enqueue(data);
}
lock (bufferMonitor) {
Monitor.PulseAll(bufferMonitor);
}
}
}
}
這個實現的問題很簡單,當一個客戶端連接到readyToSend
變化不是在第二個線程可見 - 第二個問題是,如果你把SendIfConnected
功能的斷點和更改值手動設置爲true,即使執行Monitor.PulseAll,Monitor.Wait()
也不會返回。
此外,我認爲應該存在一些簡單的解決方案,我的原始問題,並且使用一個字節[]隊列直播的整個想法是不是最好的。我希望任何一點進入更好的方向。
- readyToSend實際上設置爲true,但是線程B沒有看到這個/ Monitor.PulseAll被多次調用,在Monitor.Wait調用之前和之後。 – Etan 2011-03-28 12:29:31
@Etan:愚蠢的問題,但你確定你在同一個對象實例上調用它嗎?所以隊列填充正確? – forsvarir 2011-03-28 12:34:35
謝謝:P這是問題所在。有意思的是,有兩個實例,客戶端總是連接到沒有填充隊列的客戶端。^^如果你希望你可以重新發布你的評論作爲答案,所以我可以接受它。 – Etan 2011-03-28 13:12:03