Инкапсулируйте потоковые операции в классе, чтобы вы могли легко синхронизировать методы, чтобы сделать их потокобезопасными и заставить ReadLine замечать закрытое состояние:
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");
}
}
}
Чтобы предотвратить блокировку, которую может выполнять метод ReadLine во время ожидания полной строки, вы можете вместо этого читать символ из потока. Обратите внимание, что вам придется проверять закрытый статус внутри цикла, который читает символы:
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;
}
}
}