2008-10-29 4 views
3

TextReader에서 입력을 읽고 한 번에 한 줄씩 처리하는 백그라운드 작업을 실행하려고합니다. 사용자가 필드에 텍스트를 입력하고 제출 버튼을 클릭 할 때까지 백그라운드 작업을 차단하고 싶습니다. 텍스트를 사용할 수있을 때까지 차단할 TextReader의 맛이 있습니까? 어떻게 든 원본 소스에 텍스트를 추가 할 수 있습니까?.NET에 BlockRead StreamReader, TextReader 또는 StringReader가 있습니까?

같은 MemoryStream을 가리키는 StreamReader와 StreamWriter가 작동 할 수 있다고 생각했지만 그렇지 않습니다. StreamReader는 시작시 MemoryStream이 비어있는 것을 확인하고 다시 확인하지 않습니다.

ProcessLine() 메서드를 작성하고 사용자가 제출 단추를 클릭 할 때마다 호출하는 것이 더 쉽다는 것을 알고 있습니다. 그러나 플러그 - 인 아키텍처를 설계하려고하는데 플러그 - 인을 입력 스트림과 출력 스트림이있는 구형 콘솔 응용 프로그램처럼 보이게하고 싶습니다. 사용자가 입력 텍스트로 제출 버튼을 클릭 할 때까지 플러그인의 입력 스트림을 차단하기를 원합니다.

답변

5

유용한 구현이 될 것이므로 이상하게 생각됩니다. 그러나 간단하게 작성해야합니다. 이런 식으로 뭔가 작업을해야합니다 :

public class BlockingStream: Stream 
    { 
    private readonly Stream _stream; 

    public BlockingStream(Stream stream) 
    { 
     if(!stream.CanSeek) 
     throw new ArgumentException("Stream must support seek", "stream"); 
     _stream = stream; 
    } 

    public override void Flush() 
    { 
     lock (_stream) 
     { 
     _stream.Flush(); 
     Monitor.Pulse(_stream); 
     } 
    } 

    public override long Seek(long offset, SeekOrigin origin) 
    { 
     lock (_stream) 
     { 
     long res = _stream.Seek(offset, origin); 
     Monitor.Pulse(_stream); 
     return res; 
     } 
    } 

    public override void SetLength(long value) 
    { 
     lock (_stream) 
     { 
     _stream.SetLength(value); 
     Monitor.Pulse(_stream); 
     } 
    } 

    public override int Read(byte[] buffer, int offset, int count) 
    { 
     lock (_stream) 
     { 
     do 
     { 
      int read = _stream.Read(buffer, offset, count); 
      if (read > 0) 
      return read; 
      Monitor.Wait(_stream); 
     } while (true); 
     } 
    } 

    public override void Write(byte[] buffer, int offset, int count) 
    { 
     lock (_stream) 
     { 
     long currentPosition = _stream.Position; 
     _stream.Position = _stream.Length; 
     _stream.Write(buffer, offset, count); 
     _stream.Position = currentPosition; 
     Monitor.Pulse(_stream); 
     } 
    } 

    public override bool CanRead 
    { 
     get 
     { 
     lock (_stream) 
     { 
      return _stream.CanRead; 
     } 
     } 
    } 

    public override bool CanSeek 
    { 
     get 
     { 
     lock (_stream) 
     { 
      return _stream.CanSeek; 
     } 
     } 
    } 

    public override bool CanWrite 
    { 
     get 
     { 
     lock (_stream) 
     { 
      return _stream.CanWrite; 
     } 
     } 
    } 

    public override long Length 
    { 
     get 
     { 
     lock (_stream) 
     { 
      return _stream.Length; 
     } 
     } 
    } 

    public override long Position 
    { 
     get 
     { 
     lock (_stream) 
     { 
      return _stream.Position; 
     } 
     } 
     set 
     { 
     lock (_stream) 
     { 
      _stream.Position = value; 
      Monitor.Pulse(_stream); 
     } 
     } 
    } 
    } 
+0

고마워, 나는 이것과 비슷한 것을했지만 리더 레벨에서했다. 이것은보다 유연하게 보입니다. –

+0

이것을 구현하여 잘 작동합니다. 하나의 문제 : StreamReader와 StreamWriter를 BlockingStream에 연결하는 경우 작성기에서 AutoFlush를 설정합니다. –

5

사용자가 제출을 누를 때 발생하는 주요 응용 프로그램에서 이벤트를 만드는 것이 훨씬 낫다고 생각합니다. 텍스트 데이터는 이벤트 args에 전달됩니다. 각 플러그인은 이벤트에 대한 이벤트 핸들러를 등록하고 이벤트가 발생할 때 전달되는 데이터를 처리합니다. 이렇게하면 많은 플러그인이 사용자가 많은 배관 작업을하지 않고도 단일 제출에서 데이터를 처리 할 수 ​​있으며 이벤트가 발생할 때까지 플러그인이 유휴 상태가 될 수 있습니다.

+0

그것은 쓰는 플러그인 작가에 대한 너무 많은 간단 "{라인 = reader.ReadLine(); ...}는 않지만 (라인 = 널!);" 이벤트에 등록하는 것보다 –

+0

아마도이 비트의 코드는 더 간단 할 것이지만 스트림을 올바르게 설정하는 것은 훨씬 까다 롭습니다. 하나의 작가/여러 독자 문제 또는 통신 설정 문제가 있습니다. .NET 용 이벤트 아키텍처는 이러한 상황에 맞게 설계되었으며 잘 처리됩니다. –

+0

당신은 절대적으로 옳습니다. 그러나 인프라를 작성하고 있으며 고객들이 플러그인을 작성하고 있습니다. 나는 그들을 그들을 위해 간단하게하고 싶다. –