This is a network stream problem but i simplified test case to Console input: i started a thread ehich waits 2 seconds and closes the stream reader. But after closing stream/stream reader. While loop still waits for sr.Rea开发者_开发技巧dLine() method. i wan't to make it exit loop automatically when closes the stream/stream reader.
i tried also the thread safe version of Stream Reader; TextReader.synchronized. But the result is the same.
using System;
using System.IO;
using System.Threading;
namespace StreamReaderTest {
class Program {
static void Main(string[] args) {
new Program();
}
private StreamReader sr;
public Program() {
sr = new StreamReader(Console.OpenStandardInput());
new Thread(new ThreadStart(this.Close)).Start(); ;
string line;
while ((line = sr.ReadLine()) != null) {
Console.WriteLine(line);
}
}
public void Close() {
Thread.Sleep(2000);
sr.Close();
Console.WriteLine("Stream Closed");
}
}
}
In the console example, you may be able to use Peek to check if a character is available. For a network stream, you may be able to use Length to check if any input is available. If you don't want it to block, never read without input already pending.
Will this work for you?
class Program
{
static void Main(string[] args)
{
new Program();
}
private StreamReader sr;
private bool forcefullyClose = false;
public Program()
{
new Thread(new ThreadStart(this.Close)).Start(); ;
using (sr = new StreamReader(Console.OpenStandardInput()))
{
string line;
while (!forcefullyClose && (line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
}
public void Close()
{
Thread.Sleep(5000);
forcefullyClose = true;
Console.WriteLine("Stream Closed");
}
}
Encapsulate the stream operations in a class, so that you can easily synchronise the methods to make them thread safe and make the ReadLine notice the closed state:
using System;
using System.IO;
using System.Threading;
namespace StreamReaderTest {
class SynchronizedReader {
private StreamReader _reader;
private object _sync;
public SynchronizedReader(Stream s) {
_reader = new StreamReader(s);
_sync = new object();
}
public string ReadLine() {
lock (_sync) {
if (_reader == null) return null;
return _reader.ReadLine();
}
}
public void Close() {
lock (_sync) {
_reader.Close();
_reader = null;
}
}
}
class Program {
static void Main(string[] args) {
new Program();
}
private SynchronizedReader reader;
public Program() {
reader = new SynchronizedReader(Console.OpenStandardInput());
new Thread(new ThreadStart(this.Close)).Start();
string line;
while ((line = reader.ReadLine()) != null) {
Console.WriteLine(line);
}
}
public void Close() {
Thread.Sleep(2000);
reader.Close();
Console.WriteLine("Stream Closed");
}
}
}
To prevent the blocking that the ReadLine method can do while waiting for a complete line, you might want to read a character at a time from the stream instead. Note that you would have to check the closed status inside the loop that reads the characters:
class SynchronizedReader {
private Stream _stream;
private object _sync;
public SynchronizedReader(Stream s) {
_stream = s;
_sync = new object();
}
public string ReadLine() {
lock (_sync) {
StringBuilder line = new StringBuilder();
while (true) {
if (_stream == null) return null;
int c = _stream.ReadByte();
switch (c) {
case 10: break;
case 13:
case -1: return line.ToString();
default: line.Append((char)c);
}
}
}
}
public void Close() {
lock (_sync) {
_stream.Close();
_stream = null;
}
}
}
精彩评论