等待进程结束异步,然后调用主表单中的函数
我正在用C#编写一个游戏编辑器。 我的程序通过启动notepad.exe进程打开为.txt文件。 如果该进程退出,我想调用主窗体中的函数(更新文本框)。 这是我到目前为止所做的事情:
void OpenTextEditor(TreeNode node) { Process editor = new Process(); editor.StartInfo.WorkingDirectory = "%WINDIR%"; editor.StartInfo.FileName = "notepad.exe"; var txtfilelocation = GetRealPathByNode(node); var txtfile = File.ReadAllText(txtfilelocation,Encoding.Default); txtfile = txtfile.Replace("\n", "\r\n"); File.WriteAllText(txtfilelocation,txtfile,Encoding.Default); editor.StartInfo.Arguments = txtfilelocation; editor.EnableRaisingEvents = true; editor.Exited += delegate { NotePadHasEnded(node); }; editor.Start(); //starten } public Delegate NotePadHasEnded(TreeNode node) { var txtfilelocation = GetRealPathByNode(node); var newfileloc = txtfilelocation; var newfile = File.ReadAllText(newfileloc, Encoding.Default); newfile = newfile.Replace("\r\n", "\n"); File.WriteAllText(txtfilelocation, newfile, Encoding.Default); if (treeView1.SelectedNode == node) DisplayText(node); return null; }
GetRealPathByNode()函数返回TreeView节点指向的文件的完整路径的字符串。 DisplayText()从节点指向的文件中读取文本,并在richtextbox中显示该文本。
在执行时,我的主窗体仍然可以使用,但是当进程终止(记事本关闭)时,它会抛出一个错误,指出函数NotePadHasEnded无法访问treeView1对象,因为它正在另一个进程中执行。
如何以异步方式退出时,如何创建一个在主窗体中调用函数的进程? 我知道它在我使用WaitForExit()函数时有效,但随后我的表格冻结并等待直到记事本关闭。 我希望用户能够使用编辑器打开其他txt文件,当一个编辑器关闭时,我的GUI中的richtextbox文本正在更新。
/ 编辑 /现在已解决。 感谢伍德曼的回答,我换了
editor.Exited += delegate { NotePadHasEnded(node); };
同
editor.Exited += delegate { this.Invoke((MethodInvoker)delegate() { NotePadHasEnded(node); }); };
您应该在NotePadHasEnded()
方法中使用Dispatcher.Invoke
或Dispatcher.BeginInvoke
切换到UI线程,因为您只允许从UI线程访问UI对象。
查看此post了解更多详情。
Google for SynchronizationContext 。 发生错误的原因是您的UI线程未与运行的第二个线程同步,然后编辑器关闭。 我找到了一些描述如何实现同步的示例: 它是关于SynchronizationContext和ExecutionContext与SynchronizationContext的全部 。 希望这可以帮助你;-)
Exited
事件发生在另一个thead中,您只能访问自己的线程中的UI控件(称为UI线程)。 由于您使用的是Windows窗体,因此应使用Control.Invoke
方法:
editor.Exited += delegate { node.TreeView.Invoke(new Action(NotePadHasEnded), node); };
同时将NotePadHasEnded
的返回类型更改为void
。
node.TreeView
用于访问Invoke
方法。 您可以使用任何UI控件。 如果代码位于表单中,则可以使用this
代码。