等待进程结束异步,然后调用主表单中的函数

我正在用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.InvokeDispatcher.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代码。