[英]C# Multi threading reading from network stream
我目前正在學習如何實現多線程,因此如果這個問題真的很容易解決或/並且充滿了簡單的錯誤,我深表歉意!
我有一個程序,該程序從TCP客戶端讀取,並且我希望它輸出從網絡流中讀取的內容並將其顯示在文本框中。 流是連續的 -不斷接收數據。
我有一個線程從網絡流中讀取一行並將其附加到文本框中。 我創建了一個線程是因為我不希望它影響UI。 這是我嘗試過的代碼:
nwStream = client.GetStream();
reader = new StreamReader(nwStream);
Thread t = new Thread(ReadInandOutputToTextBoxIfInvoke);
t.Start(); //this is in the main method
private void ReadInandOutputToTextBoxIfInvoke()
{
if (Dispatcher.CheckAccess())
{
ReadInandOutputToTextBox();
}
else
{
Dispatcher.Invoke(() =>
{
ReadInandOutputToTextBox();
});
}
}
private void ReadInandOutputToTextBox()
{
for (int i = 0; i < 10; i++)
{
if (nwStream.CanRead)
{
readInTxtBox.Text = readInTxtBox.Text + reader.ReadLine();
}
}
}
但是,此代碼有兩個問題 :
它首先讀取所有行,然后顯示,而我希望它先讀取行,然后將其附加到文本框中。 例如,在一分鍾內它有一個for循環,其中包含10。 它不讀取一行,顯示並重復此操作,而是讀取全部10行,然后一次全部顯示。 我希望這是一個無限循環,因此它將不斷在流中讀取,但是這顯然是不可能的。
它在運行時確實會影響UI! 當線程正在運行時,我不能使用WPF的任何其他部分,這不是我想要的!
任何幫助/解釋將不勝感激。 我是多線程領域的新手,這是我需要大量學習的東西!
它首先讀取所有行,然后顯示,而我希望它先讀取行,然后將其附加到文本框中
您應該使用async await
而不是分解顯式且昂貴的線程。 異步/等待將使用I / O完成端口(IOCP),該端口通過不讓線程阻塞等待數據到達的方式非常有效地處理I / O。 更不用說沒有線程
您想要最小化I / O回調中的處理量(尤其是更新UI),否則會丟失數據。 例如,僅存儲接收到的數據,通過首先將接收到的數據存儲在循環緩沖區中,在不同的線程中執行處理。 您可以完全控制一次讀取多少數據,從而驅動屏幕的更新方式
它在運行時確實會影響UI! 當線程正在運行時,我不能使用WPF的任何其他部分,這不是我想要的!
不要使用Invoke
它可能導致死鎖,更重要的是會阻塞工作線程!
通過處理循環緩沖區中填充作為處理await
結果的數據來更新UI線程中的UI
我創建了一個線程是因為我不希望它影響UI。
您幾乎永遠不要使用Thread
類型。 在您的情況下,由於您正在執行I / O,所以async
/ await
更為自然:
var nwStream = client.GetStream();
var reader = new StreamReader(nwStream);
while (true)
readInTxtBox.Text = readInTxtBox.Text + await reader.ReadLineAsync();
請注意, await
不需要Invoke
/ Dispatcher
混亂,因為當await
完成時 , 它將自動與UI線程同步回去 。
嘗試在綁定數據時更改調度程序的優先級,但也僅將其用於發送結果(此方法不做任何工作):
var someNewInput = CalculateNewInput();
System.Windows.Application.Current.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.DataBind, (System.Action)delegate
{
readInTxtBox.Text += someNewInput;
});
首先,僅影響gui的代碼必須位於
if (Dispatcher.CheckAccess())
對於其余的沒問題,下面的示例(不編譯)
Task tk = Task.Factory.StartNew(() =>
{
nwStream = client.GetStream();
reader = new StreamReader(nwStream);
if (nwStream.CanRead)
int pos = await reader.ReadBlockAsync(buffer, 0, 50);
if (Dispatcher.CheckAccess())
readInTxtBox.Text = readInTxtBox.Text + buffer.toString()
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.