1

여러 장치와 통신하는 백그라운드 스레드를 실행하는 응용 프로그램이 있습니다. 장치는 내가 제어하지 않는 외부 트리거를 기반으로 데이터를 전송합니다. 기기가 데이터를 보내고 조작 할 때까지 기다려야합니다. 예외가 발생하면 해당 UI에 표시해야합니다.연속적인 TCPClient ReadAsync 네트워크 스트림 예외를 올바르게 처리하는 방법

네트워크 스트림을 통해 지속적으로 데이터를 읽으려고합니다. 데이터가 오면 이벤트로 키우고 다시 읽어야합니다. 장치 연결이 끊어지는 등 예외가 발생하면 처리 할 수 ​​있어야합니다. 기본에서

내가 네트워크 스트림을 비동기 읽기 시작, 내가 시작() 메소드를 실행하여 읽고 스레드를 시작하기에
public Task<string> ReadLinesAsync(CancellationToken token) 
    { 
     _readBuffer = new byte[c_readBufferSize]; 
     // start asynchronously reading data 
     Task<int> streamTask = _networkstream.ReadAsync(_readBuffer, 0, c_readBufferSize, token); 
     // wait for data to arrive 
     Task<String> resultTask = streamTask.ContinueWith<String>(antecedent => 
     { 
      // resize the result to the size of the data that was returned 
      Array.Resize(ref _readBuffer, streamTask.Result); 
      // convert returned data to string 
      var result = Encoding.ASCII.GetString(_readBuffer); 
      return result; // return read string 
     }, token); 
     return resultTask; 
    } 

그래서 내가 이렇게 노력하고 있어요 방법은 있습니다. 그러나 예외가 던져지면 일부 오류가 발생하더라도 프로그램이 종료됩니다. 나는 다른 곳에서 어떤 일이 발생했는지를 알기 위해 그것을 덫에 걸려 고 시도해 왔지만,이를 수행 할 수있는 적절한 방법을 찾지 못해서 응용 프로그램을 폭격하지 않고 UI에 오류를 제기 할 수 있습니다.

async public override void Start() 
    { 
     try 
     { 
      await _client.ReadLinesAsync(_cts.Token).ContinueWith(ReadLinesOnContinuationAction, _cts.Token); 
     } 
     catch (AggregateException ae) 
     { 
      ae.Handle((exc) => 
      { 
       if (exc is TaskCanceledException) 
       { 

        _log.Info(Name + " - Start() - AggregateException" 
         + " - OperationCanceledException Handled."); 
        return true; 
       } 
       else 
       { 
        _log.Error(Name + " - Start() - AggregateException - Unhandled Exception" 
        + exc.Message, ae); 
        return false; 
       } 
      }); 
     } 
     catch (Exception ex) 
     { 
      _log.Error(Name + " - Start() - unhandled exception.", ex); 
     } 
    } 
async private void ReadLinesOnContinuationAction(Task<String> text) 
    { 
     try 
     { 
      DataHasBeenReceived = true; 
      IsConnected = true; 
      _readLines.Append(text.Result); 
      if (OnLineRead != null) OnLineRead(Name, _readLines.ToString()); 
      _readLines.Clear(); 
      await _client.ReadLinesAsync(_cts.Token).ContinueWith(ReadLinesOnContinuationAction, _cts.Token); 
     } 
     catch (Exception) 
     { 
      _log.Error(Name + " - ReadLinesOnContinuationAction()"); 
     } 
    } 

디버거는 일반적으로 라인에 중지 : _readLines.Append(text.Result); 나는 text.IsFaulted 플래그에 대한 검사에서이 퍼팅 시도했지만 그때는 .ContinueWith에 폭격.

아무도 내가 제대로 잡을 수 있도록 오류를 수정하고 UI를 고를 수 있도록이 문제를 해결할 필요가있는 아이디어가 있습니까? 이 코드에는 모든 종류의 악취가 있지만, 나는 이것을 배우고 있습니다. 당신이 줄 수있는 도움을 주셔서 감사합니다.

답변

1

폭격과 함께 계속됩니까? 적어도 두 가지가 있습니다.

개인적으로, 나는 ContinyncWith와 비동기/대기를 혼합하지 않을 것입니다. 기다림은 이미 당신에게 ContinueWith를 할 수있는 편리한 방법을 제공합니다, 그래서 그것을 사용하십시오. 예 :

public async Task<string> ReadLinesAsync(CancellationToken token) 
{ 
    _readBuffer = new byte[c_readBufferSize]; 
    // start asynchronously reading data 
    int readResult = await _networkstream.ReadAsync(_readBuffer, 0, c_readBufferSize, token); 
    // after data arrives... 

    // resize the result to the size of the data that was returned 
    Array.Resize(ref _readBuffer, streamTask.Result); 
    // convert returned data to string 
    return Encoding.ASCII.GetString(_readBuffer); 
} 

async public override void Start() 
{ 
    try 
    { 
     string text = await _client.ReadLinesAsync(_cts.Token); 
     await ReadLinesOnContinuationAction(text); 
    } 
    catch (AggregateException ae) 
    { 
     ae.Handle((exc) => 
     { 
      if (exc is TaskCanceledException) 
      { 

       _log.Info(Name + " - Start() - AggregateException" 
        + " - OperationCanceledException Handled."); 
       return true; 
      } 
      else 
      { 
       _log.Error(Name + " - Start() - AggregateException - Unhandled Exception" 
       + exc.Message, ae); 
       return false; 
      } 
     }); 
    } 
    catch (Exception ex) 
    { 
     _log.Error(Name + " - Start() - unhandled exception.", ex); 
    } 
} 

async private Task ReadLinesOnContinuationAction(Task<String> text) 
{ 
    try 
    { 
     DataHasBeenReceived = true; 
     IsConnected = true; 
     _readLines.Append(text.Result); 
     if (OnLineRead != null) OnLineRead(Name, _readLines.ToString()); 
     _readLines.Clear(); 
     string text = await _client.ReadLinesAsync(_cts.Token); 
     await ReadLinesOnContinuationAction(text); 
    } 
    catch (Exception) 
    { 
     _log.Error(Name + " - ReadLinesOnContinuationAction()"); 
    } 
} 

또는 이와 비슷한 것입니다. 위의 내용은 분명히 편집되지 않았으며 올바른 결과를 얻기 위해 약간의 마사지가 필요할 수 있습니다. 그러나 잘하면 일반적인 아이디어는 충분히 명확하다.

+0

ReadLinesOnContinuationAction을 계속했습니다. 답장을 보내 주셔서 감사합니다. 나는 그것에 대해서 생각조차하지 않았다. 나는 그것을 오늘 아침에 시험해보고 당신에게 알려줄 것입니다. – evclay