C# C多线程读取网络流

C# C多线程读取网络流,c#,wpf,multithreading,C#,Wpf,Multithreading,我目前正在学习如何实现多线程,如果这个问题真的很容易解决或/或充满了简单的错误,我深表歉意 我有一个从TCP客户端读取的程序,我希望它输出从网络流读取的内容,并将其显示在文本框中。流是连续的-数据不断地被接收 我有一个线程,它从网络流中读取一行内容并将其附加到文本框中。我创建了一个线程,因为我不希望它影响UI。以下是我尝试过的代码: nwStream = client.GetStream(); reader = new StreamReader(nwStream);

我目前正在学习如何实现多线程,如果这个问题真的很容易解决或/或充满了简单的错误,我深表歉意

我有一个从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,而不是旋转显式和昂贵的线程。async/await将使用I/O完成端口IOCP,它通过不让线程阻塞等待数据到达而非常有效地处理I/O。更不用说没有线索了

您希望最小化处理量,尤其是在I/O回调中更新UI,否则将丢失数据。例如,仅存储接收到的数据,通过首先将接收到的数据存储在循环缓冲区中,在不同的线程中执行处理。您可以完全控制一次读取的数据量,从而驱动屏幕的更新方式

它在运行时确实会影响UI!当线程运行时,我不能使用WPF的任何其他部分,这不是我想要的

不要使用Invoke,它会导致死锁,更重要的是会阻塞工作线程

在UI线程中通过处理循环缓冲区中的数据更新UI,该缓冲区作为处理等待的结果填充


首先,只有影响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()

    };

尝试在绑定数据时更改dispatcher优先级,但也仅用于发送结果,而不使用此方法:

var someNewInput = CalculateNewInput();
System.Windows.Application.Current.Dispatcher.Invoke(
        System.Windows.Threading.DispatcherPriority.DataBind, (System.Action)delegate
        {
            readInTxtBox.Text += someNewInput;
        });
我创建了一个线程,因为我不希望它影响UI

您几乎不应该使用螺纹类型。在您的情况下,因为您正在进行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混乱,因为。

除非您使用的是低于4的.NET版本,没有充分的理由让您使用Thread类而不是Taskclass@CamiloTerevinto如果您使用的是低于4,那么仍然没有很好的理由,因为有更好的机制,比如在许多类型上使用XxxxxBegin和XXXXXEND异步方法,或者通过使用ThreadPool.QueueUserWorkItem…Dispatcher.Invoke在用户界面线程。所以你在UI线程上做所有的线程工作,所以它不能更新。如果你总是每隔几毫秒更新一次UI,我希望这是一个无限循环,这样它就会不断地在流中读取,你就会用所有这些更新冻结UI。和readInTxtBox.Text+reader.ReadLine;在无限循环中,将导致应用程序减速并最终崩溃。使用Task.Run代替或至少通过TaskScheduler。默认为参数之一。哦,恐怕。您应该尝试回答这个问题,而不是在线程和并行性问题上再次争论。当你知道自己在做什么时,新任务并不比其他任务更危险,除了在不应该的时候使用StartNew之外,你的答案有一个相当大的问题。除非你遇到我链接到readInTxtBox.Text=readInTxtBox.Text+buffer.toString的坏情况,否则CheckAccess将永远不会运行。哦,我担心-别傻了这很好,唯一的问题是当使用whiletrue循环时,它会持续运行,大约14/15次后会冻结。最终,您必须重写它,使其具有一定的刷新率(例如,每1秒更新一次),或者按照MickyD的建议,必须重写它以使用async/await