Выход из цикла while, когда поток закрыт? - PullRequest
0 голосов
/ 17 января 2010

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

я пробовал также потоковую версию 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");
    }
  }
}

Ответы [ 3 ]

1 голос
/ 17 января 2010

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

0 голосов
/ 17 января 2010

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

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");
    }
}
0 голосов
/ 17 января 2010

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

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...