2012-02-15 21 views
0

我有一臺運行的TCP服務器,它定期以2字節的形式發送消息。取消從網絡流中不斷讀取的後臺工作人員

我試圖創建一個連接到服務器的客戶端端表單,並不斷從流中讀取,直到我單擊窗體上的斷開連接按鈕。

到目前爲止客戶端工作正常,但我不能斷開連接。我將CancellationPending設置爲true,但在dowork方法有機會設置e.Cancel之前,它似乎重置爲false。

我也確定必須有一個更可接受的方式來連續讀取流並寫入表單 - 目前我在Worker Completed方法中調用RunWorkerAsync來實現循環!

private void Disconnect() 
    { 
     commsWorker1.CancelAsync(); 
    } 

    private void ReadFromStream() 
    { 
     try 
     { 
      commsWorker1.RunWorkerAsync(); 
     } 
     catch (Exception ex) 
     { 
      writeToBox("Error: " + ex.Message); 
     } 
    } 

    //background worker dowork method 
    private void BackGroundGetServerData(object sender, DoWorkEventArgs e) 
    { 
     if (true == commsWorker1.CancellationPending) 
     { 
      e.Cancel = true; 
     } 
     else 
     { 
      Byte[] dataArray = new Byte[2]; 
      try 
      { 
       _DataStream.Read(dataArray, 0, 2); 
       String reply = System.Text.Encoding.ASCII.GetString(dataArray); 
       e.Result = reply; 
      } 
      catch (Exception ex) 
      { 
      } 
     } 
    } 

    //background worker workercompleted method 
    private void BackGroundDisplayMessages(object sender, RunWorkerCompletedEventArgs e) 
    { 
     if (e.Cancelled) 
     { 
      //close connection here 
     } 
     else 
     { 
      writeToBox((String)e.Result); 
      commsWorker1.RunWorkerAsync(); 
     } 

    } 
} 

}

+0

您是否將WorkerSupportsCancellation設置爲true? – Archeg 2012-02-15 11:18:28

+0

對不起,應該注意的是,WorkerSupportsCancellation和WorkerSupportsProgress都是真實的。 – David 2012-02-15 11:19:55

回答

0

你就不能在後臺工作方法內循環?

private void BackGroundGetServerData(object sender, DoWorkEventArgs e) 
{ 
    while(true) 
    { 
     Byte[] dataArray = new Byte[2]; 
     try 
     { 
      _DataStream.Read(dataArray, 0, 2); 
      String reply = System.Text.Encoding.ASCII.GetString(dataArray); 
      e.Result = reply; 
     } 
     catch (Exception ex) 
     { 
      return; 
     } 
    } 
} 

然後斷開後,只需關閉插座。這將導致Exception在while循環中拋出,並且您可以通過catch塊優雅地退出。

Edit:然後,您可以在讀取每條消息後從循環更新GUI。確保手柄要更新可用(假定這就是所謂box)控制:

delegate void updateDelegate(String p); 

private void BackGroundGetServerData(object sender, DoWorkEventArgs e) 
{ 
    while(true) 
    { 
     Byte[] dataArray = new Byte[2]; 
     try 
     { 
      _DataStream.Read(dataArray, 0, 2); 
      String reply = System.Text.Encoding.ASCII.GetString(dataArray); 
      box.BeginInvoke(new updateDelegate(writeToBox), reply); 
     } 
     catch (Exception ex) 
     { 
      return; 
     } 
    } 
} 

BeginInvoke需要在這種情況下,因爲你要更新從另一個線程,這是不允許的GUI。此方法將更新轉發到GUI線程。

+0

在這種情況下BackGroundDisplayMessages如何被調用?如果我在DoWork方法中循環,那麼我認爲,WorkerCompleted方法永遠不會被調用,所以從流中讀取的值永遠不會顯示? – David 2012-02-15 11:17:01

+0

@David:看我的編輯。 – Tudor 2012-02-15 11:26:08

+0

感謝都鐸,非常感謝,我採取了你的方法,它完成了這項工作! – David 2012-02-15 11:40:38

0

看起來您正在調用Worker Complete方法中的RunWorkerAsync()並重置您的CancellationPending prop。我認爲你可以嘗試通過添加Disconnect()方法來解決這個問題disconnectFlag = true;並且在WorkerComplete方法中,您應該添加:

if (e.Cancelled || disconnectFlag) 
    { 
     disconnectFlag = false; 
     //close connection here 
    } else ... 
+0

謝謝你Archeg – David 2012-02-15 11:40:11