Streaming data over sockets
I want to broadcast live data from one server to multiple clients using 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);
}
}
}
}
The problem with this implementation is simply, that the change to readyToSend
when a client connects is not visible in the se开发者_运维知识库cond thread - the second problem is, that if you put a breakpoint in the SendIfConnected
function and change the value manually to true, that the Monitor.Wait()
will never return although Monitor.PulseAll is executed.
Also, I kind of think that there should exist some easy solution to my original problem and that the whole idea of using a byte[] Queue for a live broadcast isn't the best one. I would appreciate any point into some better direction.
I can't help but feel like there's some information missing here.
In the code that's given, bufferMonitor is never initialized. If it isn't done in some code that you haven't included, then I would be expecting the lock call to fail.
You appear to be saying that readyToSend is never set to true. From the code supplied, this would suggest that the clientConnected method is never being called, or [...] is throwing/returning before that line of the method is executed. Are you sure clientConnected is being called?
Where does 'put a break point there' refers to?
As I understand it, the Monitor.Wait (assuming the lock object has been created) is only going to return if the Monitor.PulseAll is executed, after thread A has gone into a wait state. Are you sure that this is the sequence of events that's happening? If the pulse happens before wait is called, the thread won't wake up.
Stupid question, but are you sure you're calling it on the same instance of the object? So the queue is populated correctly?
精彩评论