我目前正在学习如何实现多线程,所以如果这个问题很容易解决或者/并且充满了简单的错误我会道歉!
我有一个程序,它从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();
}
}
}
但是,此代码有两个问题:
第一个问题是它在所有行中读取然后显示,而我希望它读取一行然后将其附加到文本框。例如,它有一个10循环的for循环。它不是在一行中读取,显示它,而是重复这一行,而是读取所有10行,然后一次显示所有行。我希望这是一个无限循环,所以它会不断地在流中读取,但这显然是不可能的。
运行时会影响用户界面!当线程运行时,我不能使用WPF的任何其他部分,这不是我想要的!
任何帮助/解释都会受到广泛赞赏。我是多线程的完全新手,这是我需要大大改进的事情!
答案 0 :(得分:3)
第一个问题是它在所有行中读取然后显示,而我希望它读取一行然后将其附加到文本框
您应该使用async await
而不是使用明确且昂贵的线程。 async / await将使用I / O完成端口(IOCP),它通过不让线程阻塞等待数据到达来非常有效地处理I / O.更不用说没有线程了
您希望在I / O回调中最小化处理量(特别是更新UI),否则您将丢失数据。例如,仅存储接收的数据,通过首先将接收的数据存储在循环缓冲器中来执行不同线程中的处理。您可以完全控制一次读取的数据量,从而推动屏幕更新的方式
运行时会影响用户界面!当线程运行时,我不能使用WPF的任何其他部分,这不是我想要的!
不要使用Invoke
它会导致死锁,更重要的是会阻塞工作线程!
通过处理由于处理await
答案 1 :(得分:0)
我创建了一个帖子,因为我不希望它影响用户界面。
您几乎不应该使用from pyspark.sql import SparkSession
my_spark = SparkSession \
.builder \
.appName("myApp") \
.config("spark.mongodb.input.uri", "mongodb://127.0.0.1/test.coll") \
.getOrCreate()
df = spark.read.format("com.mongodb.spark.sql.DefaultSource").load()
filtrDf = df.filter(df['deleted_at'] == 'null')
filtrDf.explain() // check for physical plan of this output
类型。在您的情况下,由于您正在进行I / O,Thread
/ async
更加自然:
await
请注意,var nwStream = client.GetStream();
var reader = new StreamReader(nwStream);
while (true)
readInTxtBox.Text = readInTxtBox.Text + await reader.ReadLineAsync();
不需要await
/ Invoke
混乱,因为it automatically syncs back up with the UI thread when the await
completes。
答案 2 :(得分:-1)
尝试在绑定数据时更改调度程序优先级,但也只使用它来发送结果(不在此方法中工作):
var someNewInput = CalculateNewInput();
System.Windows.Application.Current.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.DataBind, (System.Action)delegate
{
readInTxtBox.Text += someNewInput;
});
答案 3 :(得分:-3)
首先,只有影响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()
};