2010-01-17 2 views
0

Это проблема сетевого потока, но я упростил тестовый сценарий для ввода в консоль: Я начал поток, который ждет 2 секунды и закрывает считыватель потока. Но после закрытие потока/потокового считывателя. Пока цикл все еще ждет метода sr.ReadLine(). i wan't, чтобы автоматически завершить цикл выхода, когда закрывает средство чтения потока/потока.Выход из цикла while при закрытии потока?

Я попробовал также потокобезопасную версию Stream Reader; TextReader.synchronized. Но результат тот же.

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"); 
    } 
    } 
} 
+0

related: http://stackoverflow.com/questions/981196/how-to-know-if-a-bufferedreader-stream-is-closed –

+0

Не должно ли StreamReader находиться под полным контролем? Возможно, этот пример немного вводит в заблуждение. – ziya

+1

В случае сетевого потока я бы * ожидал *, что он уже работает; Я * подозреваю * тонкости закрытия текущих процессов собственным входным потоком могут путать вещи здесь? –

ответ

0

Инкапсулируйте операции потока в классе, так что вы можете легко синхронизировать методы, чтобы сделать их поточно и сделать 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; 
    } 
    } 

} 
+0

Да, но читатель все еще ждет дополнительного «ввести символ». –

+0

@ Fırat: Да, метод ReadLine может блокировать поток, если линия не завершена. Вы должны были бы прочитать персонажа за раз, чтобы обойти это. – Guffa

+0

Я пробовал то же самое. Я использовал метод Stream.readByte(). –

0

Будет ли это работать на вас?

+0

Не жалко. Такая же ситуация. –

1

В примере консоли вы можете использовать Peek, чтобы проверить, доступен ли символ. Для сетевого потока вы можете использовать длину, чтобы проверить, доступен ли какой-либо вход. Если вы не хотите, чтобы он блокировался, никогда не читайте без ввода уже ожидающего ввода.

Смежные вопросы