Val*_*tor 2 .net c# multithreading winforms
在Windows窗体项目中,我有一个按钮处理程序,可以在记事本中打开文件进行编辑.一旦记事本关闭,我调用一个函数RefreshTextBox()
来解析文本文件并根据值更新TextBox.以下是打开记事本并在关闭时调用refresh方法的方法:
private void button_Click(object sender, EventArgs e)
{
Process p = new Process
{
EnableRaisingEvents = true,
StartInfo =
{
FileName = "NOTEPAD.EXE",
Arguments = _path,
WindowStyle = ProcessWindowStyle.Maximized,
CreateNoWindow = false
}
};
p.Exited += (a, b) =>
{
RefreshTextBox();
p.Dispose();
};
p.Start();
}
Run Code Online (Sandbox Code Playgroud)
和刷新文本框的代码:
private void RefreshTextBox()
{
using (StreamReader reader = File.OpenText(_appSettingsPath))
{
string text = reader.ReadToEnd();
// Code to parse text looking for value...
// InvalidOperationException thrown here:
textBox.Text = reader.Value.ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
这会引发一个异常,试图从一个创建它的线程以外的线程更新Control.我很难理解为什么.我不会在新的任务或背景工作者或类似的事情中这样做.显然,记事本正在另一个线程中运行,但刷新方法直到它的进程退出后才会被调用.
编辑:我应该补充一点,在Visual Studio(作为管理员)中进行调试时,此错误会抛出致命异常弹出窗口.它自己运行应用程序时不会显示弹出窗口,要么是静默吞下,要么就不会出现异常.
根据文档,如果SynchronizingObject
未设置Process ,它将在系统线程池中执行exited事件以避免这种情况并在UI线程中运行该事件处理程序,您需要将其设置SynchronizingObject
为Form Instance
当SynchronizingObject为null时,将在系统线程池的线程上调用处理Exited事件的方法.有关系统线程池的更多信息,请参阅
ThreadPool
.
如果你设置
p.SynchronizingObject = WindowsFormName;
Run Code Online (Sandbox Code Playgroud)
然后它将在同一个线程中运行,否则它将在系统线程池线程中执行,这将导致交叉线程异常.
归档时间: |
|
查看次数: |
90 次 |
最近记录: |