I have a proxy server I’m writing in C#. I also have a Java applet that receives MJPEG data from a video server through this C# proxy. My problem is that when no more MJPEG data is currently available from the video server, the proxy is stuck in a blocking read call and I cannot terminate it.
// write the forwarded output
// blocking on remoteServerResponseStream.Read
while (m_running && (read = remoteServerResponseStream.Read(buffer, 0, buffer.Length)) > 0)
{
bytesRead += read;
output.Write(buffer, 0, read);
output.Flush();
}
This should be terminated by the Java applet closing the stream (variable output in code above). However, the Java applet cannot close this connection because the proxy never acknowledges the close request while it is stuck in remoteServerResponseStream.Read waiting for data.
I have been stuck on this problem for a week. I think I might have thought of a solution but I’m not sure if it will work. I’d love to hear any feedback on this.
My thought was to have the removeServerResponseStream.Read on another thread and use a shared Queue to transfer data. The thread would read data and place it on the queue. My main thread would then forward any data available in the queue to output. This way, I can constantly check if output.CanWrite ever becomes false, in which case I can abort the read thread (this is the only way I know of to interrupt a blocking stream read). Is this a viable solution? If so, should I constantly poll the queue for data available or should I create an event? I’d love to hear any thoughts on this problem! Thanks in advance.
In these situations I just end the stream reader from another thread. When you close the reader it will break the loop. Going through extra synchronized queues is just more boilerplate to do unnecessarily. Eventually somewhere you have to stop the blocking reader. Putting values in a queue only stops your consumer from being blocked, but not your reader.
Here is an example with a socket blocking read. I will be blocking on reading 1 byte which I’ll intentionally never send. A couple seconds later I’ll dispose of the socket, the socket will bail out of its blocking read and the app will exit gracefully. I’ll log what each thread is doing and when it happens (the number prefixing each log line is the thread id and I’ll indent separate threads).
In your class that uses the blocking reader you should implement the Disposable pattern and close/dispose of your reader there.
When you run this you get:
You kind of answered the question yourself here though:
Which is exactly what you should do. When you know your app has closed close the socket from the active thread. This free’s the blocked thread and you can gracefully end.
The pattern here is you usually spin up a thread for a specific socket and you maintain one active thread that is a kind of “controller” thread for requests.