【发布时间】:2020-02-01 05:05:35
【问题描述】:
我的程序在计时器事件中显示时间,button 启动一个函数,该函数不断读取文件的内容,直到达到 50 行。
测试文件由不同的process 创建,偶尔会在其上附加一些行。
如何修改程序以避免在执行期间阻塞表单 执行?
与WinForm Application UI Hangs during Long-Running Operation 相比的不同之处在于调用的函数必须更新表单的某些元素。
而且我不想使用 Application.DoEvents(), 我的程序中有数百行 Application.DoEvents(),有时它们会造成混乱。
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
void Timer1Tick(object sender, EventArgs e)
{
UpdateTime();
}
void UpdateTime()
{
DateTime dt = DateTime.Now;
textBox1.Text = dt.ToString("hh:mm:ss");
}
void BtnRunClick(object sender, EventArgs e)
{
int nlines = 0;
while(nlines < 50) {
nlines = listBox1.Items.Count;
this.Invoke(new Action(() => ReadLinesFromFile()));
Thread.Sleep(1000);
}
}
void ReadLinesFromFile()
{
string sFile = @"D:\Temp1\testfile.txt";
string[] lines = File.ReadAllLines(sFile);
listBox1.Items.Clear();
foreach(string line in lines) {
listBox1.Items.Add(line);
listBox1.SelectedIndex = listBox1.Items.Count - 1;
}
}
}
【问题讨论】:
-
不完全。如果我将代码更改为 Task.Run(() => MyRunFunction()); MyRunFunction() 函数不会更新 listBox1。
-
你启动线程了吗(
t.Start())?而且,如果您错过了:“请记住,使用任何线程,您无法更新 GUI,或从后台线程更改任何 GUI 控件。如果您想在 GUI 上执行任何操作,您必须使用 Invoke(和 InvokeRequired)在 GUI 线程上触发该方法。" -
当我使用 t.Start() 时,我得到 System.InvalidOperationException: Cross-thread operation not valid: Control 'listBox1' 从创建它的线程以外的线程访问。
-
“如果你想在 GUI 上做任何事情,你必须使用 Invoke(和 InvokeRequired)在 GUI 线程上触发该方法。”
-
我对代码进行了一些更改,现在后台线程更新了表单上的数据。主要的代码行是 this.Invoke(new Action(() => RunFunction()));但这仍然会阻止表单