C# 控件在调用其调用方法后不会更新
已编辑并要求重新打开 我的问题被搁置了,因为它被认为是离题的,我没有添加任何源代码。在我看来,没有必要添加源代码,因为我写了一个简单的问题,没有任何源代码都可以回答:“现在,我的假设是线程被终止,因此调用不再被调用。这是否合理?”这个问题已经得到了回答,我知道这不是原因。当时添加一些源代码是有意义的。我认为现在这个问题应该符合你的要求(尽管我仍然认为一开始不是这样:-)。无论如何,你能重新回答这个问题吗 结束要求重新打开的请求 我有一个C#程序,我想从另一个线程更新两个控件。 第一次更新运行得很好。文本按预期显示。但是第二个文本框不再填充。第二个调用完全在线程的“末尾”调用 如果我在调用后添加一个C# 控件在调用其调用方法后不会更新,c#,multithreading,C#,Multithreading,已编辑并要求重新打开 我的问题被搁置了,因为它被认为是离题的,我没有添加任何源代码。在我看来,没有必要添加源代码,因为我写了一个简单的问题,没有任何源代码都可以回答:“现在,我的假设是线程被终止,因此调用不再被调用。这是否合理?”这个问题已经得到了回答,我知道这不是原因。当时添加一些源代码是有意义的。我认为现在这个问题应该符合你的要求(尽管我仍然认为一开始不是这样:-)。无论如何,你能重新回答这个问题吗 结束要求重新打开的请求 我有一个C#程序,我想从另一个线程更新两个控件。 第一次更新运行得很
MessageBox.Show(“…”)
,它就会被填充。
现在,我的假设是线程被终止,因此,调用不再被调用。
这听起来合理吗?
即使在线程结束时,我还能做些什么来更新文本框
以下是代码(或部分代码)
按下按钮后将调用该任务:
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = AppDomain.CurrentDomain.BaseDirectory + "\\iperf3.exe",
Arguments = "[...]",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true,
RedirectStandardError = true
}
};
proc.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
proc.ErrorDataReceived += new DataReceivedEventHandler(ErrorHandler);
proc.Exited += new EventHandler(ExitHandler);
proc.EnableRaisingEvents = true;
proc.Start();
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
}
流程完成后,它将调用ExitHandler方法(该方法反过来启动一个新流程:
private void ExitHandler(object sender, EventArgs e)
{
proc.CancelErrorRead();
proc.CancelOutputRead();
proc.Dispose();
proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = AppDomain.CurrentDomain.BaseDirectory + "\\iperf3.exe",
Arguments = "[...]",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true,
RedirectStandardError = true
}
};
proc.OutputDataReceived += new DataReceivedEventHandler(OutputHandler2);
proc.ErrorDataReceived += new DataReceivedEventHandler(ErrorHandler);
proc.Exited += new EventHandler(ExitHandler2);
proc.EnableRaisingEvents = true;
proc.Start();
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
}
第二个线程完成后,启动以下方法:
private void ExitHandler2(object sender, EventArgs e)
{
MessageBox.Show("Command exited.", "Information"); // When commenting this line, labl2 is not filled anymore, see below /*****/
proc.CancelErrorRead();
proc.CancelOutputRead();
button1.Invoke(new Action(() => button1.Enabled = true));
proc.Dispose();
}
文本框的更新是通过解析进程的输出来实现的。这些更新由OutputHandler方法接收:
对于第一个任务:
void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
...
label1.Invoke(new Action(() => label1.Text = "[some captured text]")); // This part is always working
...
}
第二项任务也是如此:
void OutputHandler2(object sendingProcess, DataReceivedEventArgs outLine)
{
...
label2.Invoke(new Action(() => label2.Text = "[some captured text]")); // This one is only working when showing a MessagBox on ExitHandler2
}
label2中的文本仅在执行MessageBox.Show命令时显示(标记为/*****/)
解决方案
因为我不能把这个作为问题的答案,所以我在这里加上这个。也许这对某人有帮助。
在尝试对代码进行不同更改几天后,我发现proc.CancelOutputRead();
指令正在阻止表单更新。在停止读取输出时,输出似乎尚未完全解析。删除此指令(以及proc.Dispose()时)
说明,数值显示正确。
然后在主窗体的onClosing
事件处理程序中进行proc.Dispose()
调用。
感谢您的支持!处于“线程末尾”不会有任何区别。调用是同步调用的,这意味着您的代码将等待完成。我认为您的代码中存在不同的问题。发布它!现在正如您所说的那样…我将修改它。(我从互联网上截取了一些片段,没有过多考虑这是否有意义。)也许,不需要一个
进程
…如果你把这个作为答案写,我会把它标记为正确答案。谢谢。实际上我需要创建一个新的进程,因为我正在运行一个控制台应用程序,这肯定是一个新的进程。当然,我可以创建一个单独的线程,然后在该线程中启动控制台应用程序,但我不能他还将创建一个单独的进程,所以如果创建了一个新的进程,就不需要再创建新的线程。我认为这样可以节省资源,让事情更清楚。