簡體   English   中英

從網絡流讀取C#多線程

[英]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();
            }
        }

    }

但是,此代碼有兩個問題

  1. 它首先讀取所有行,然后顯示,而我希望它先讀取行,然后將其附加到文本框中。 例如,在一分鍾內它有一個for循環,其中包含10。 它不讀取一行,顯示並重復此操作,而是讀取全部10行,然后一次全部顯示。 我希望這是一個無限循環,因此它將不斷在流中讀取,但是這顯然是不可能的。

  2. 它在運行時確實會影響UI! 當線程正在運行時,我不能使用WPF的任何其他部分,這不是我想要的!

任何幫助/解釋將不勝感激。 我是多線程領域的新手,這是我需要大量學習的東西!

它首先讀取所有行,然后顯示,而我希望它先讀取行,然后將其附加到文本框中

  1. 您應該使用async await而不是分解顯式且昂貴的線程。 異步/等待將使用I / O完成端口(IOCP),該端口通過不讓線程阻塞等待數據到達的方式非常有效地處理I / O。 更不用說沒有線程

  2. 您想要最小化I / O回調中的處理量(尤其是更新UI),否則會丟失數據。 例如,僅存儲接收到的數據,通過首先將接收到的數據存儲在循環緩沖區中,在不同的線程中執行處理。 您可以完全控制一次讀取多少數據,從而驅動屏幕的更新方式

它在運行時確實會影響UI! 當線程正在運行時,我不能使用WPF的任何其他部分,這不是我想要的!

  1. 不要使用Invoke它可能導致死鎖,更重要的是會阻塞工作線程!

  2. 通過處理循環緩沖區中填充作為處理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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM