2014-10-19 48 views
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; 
    } 

所以我試圖做到這一點的方法是在啓動時,我開始一個線程,通過運行Start()方法讀取。但是當拋出一個異常時,即使我在周圍放置了一些錯誤,也會殺死我的程序。我一直試圖在不同的地方捕捉它,只是爲了看看會發生什麼,但我一直無法找出正確的方法來做到這一點,以便我可以在不轟炸我的應用程序的情況下將錯誤提交給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。

有沒有人有任何想法,我需要解決這個問題,以便我可以正確地捕捉錯誤,並提高甚至到用戶界面?這段代碼有各種各樣的不好的氣味,但我正在學習這一點。謝謝你提供的所有幫助。

回答

1

被炸死的與ContinueWith?你至少有兩個我看到的。

就我個人而言,我不會與ContinueWith混合異步/等待。等待已經給你一個方便的方法去做一個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 2014-10-20 09:23:44