我正在用 c# 撰寫一個簡單的 tcp 通信程式。我想要的是通過在客戶端收到特定訊息時啟用它來啟動計時器。問題是,定時器在啟用時不會滴答作響。我正在使用 System.Windows.Forms.Timer。
void ReceiveData()
{
int recv;
string stringData;
while (true)
{
recv = client.Receive(data);
stringData = Encoding.ASCII.GetString(data, 0, recv);
if (stringData == "/starttimer" & !timer1.Enabled)
{
timer1.Enabled = true;
break;
}
}
}
Stopwatch player1timer = new Stopwatch();
void timer1_Tick(object sender, EventArgs e)
{
if (player1timer.IsRunning)
{
pl1label.Text = Convert.ToDouble(2) - Convert.ToDouble(player1timer.Elapsed.Minutes.ToString("00")) ":"
Convert.ToString(Convert.ToDouble(59) - Convert.ToDouble(player1timer.Elapsed.Seconds.ToString("00"))) "."
Convert.ToString(Convert.ToDouble(999) - Convert.ToDouble(player1timer.Elapsed.Milliseconds.ToString("00")));
}
}
uj5u.com熱心網友回復:
由于這是一個 UI 程式,您需要小心避免阻塞 UI 執行緒。
在您的示例中,Receive可能會阻塞 UI 執行緒,直到有一些資料。如果計時器已經啟用,或者它沒有收到所需的訊息,它將繼續這樣做。這將阻止 UI 執行其他操作,例如更新圖形或處理滑鼠和鍵盤事件。永遠不要阻塞 UI 執行緒
為避免這種情況,您需要使用異步編程或后臺執行緒。由于后臺執行緒需要對執行緒安全有相當好的理解,我建議使用異步方法。
我沒有任何完整的例子,如果這是家庭作業,這樣的例子可能會適得其反,但總體方法應該是:
- 從TcpListner創建 TcpClient
- 從
TcpClient.GetStream() - 將此流包裝在 streamReader 中,并用于
ReadLineAsync()讀取行。在創建閱讀器時使用您想要的任何文本編碼。 - 等待回傳的任務以獲取實際的字串。
您可以在異步方法內的無限回圈中執行此操作。這不應該阻塞,因為它await會讓 UI 執行緒在等待資料時做其他事情。請記住將方法的內容包裝在 try/catch 中,否則例外可能會丟失。
這應該適用于演示概念的簡單應用程式,但對于實際使用,我強烈建議使用庫來處理通信。這很可能會更容易使用。
請注意,一些回傳任務的方法是謊言,并且是假裝異步的真正同步方法。這顯然行不通,但從檔案中很難分辨,因此嘗試通常是最簡單的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/484609.html
