等待进程结束异步,然后调用主窗体中的函数
本文关键字:窗体 函数 调用 然后 进程 结束 异步 等待 | 更新日期: 2023-09-27 18:00:37
我正在用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节点指向的File的完整路径字符串。DisplayText()从节点指向的文件中读取文本,并将其显示在richtext框中。
执行后,我的主窗体仍然可以按我的意愿使用,但当进程终止(记事本关闭)时,它会抛出一个错误,指出函数NotePadHasEnded无法访问treeView1对象,因为它正在另一个进程中执行。
如何创建一个进程,在退出主窗体时异步调用该函数?我知道当我使用WaitForExit()函数时它是有效的,但随后我的Form冻结并等待记事本关闭。我希望用户能够使用编辑器打开其他txt文件,并且当一个编辑器关闭时,richtextbox文本将在我的GUI中更新。
/编辑/现已解决。多亏了Woodman的回答,我取代了
editor.Exited += delegate {
NotePadHasEnded(node);
};
带有
editor.Exited += delegate
{
this.Invoke((MethodInvoker)delegate()
{
NotePadHasEnded(node);
});
};
您应该在NotePadHasEnded()
方法中使用Dispatcher.Invoke
或Dispatcher.BeginInvoke
切换到UI线程,因为您只允许从UI线程访问UI对象。
查看此帖子以了解更多详细信息。
Google for SynchronizationContext。发生此错误的原因是UI线程未与运行的第二个线程同步,然后编辑器关闭。我发现了几个描述如何实现同步的例子:It’s All About the SynchronizationContext和ExecutionContext vs SynchronizaContext。希望这对你有所帮助;-)
Exited
事件发生在另一个线程中,并且您只能在它们自己的线程(称为UI线程)中访问UI控件。由于您使用的是Windows窗体,因此应该使用Control.Invoke
方法:
editor.Exited += delegate
{
node.TreeView.Invoke(new Action<TreeNode>(NotePadHasEnded), node);
};
同时将NotePadHasEnded
的返回类型更改为void
。
CCD_ 8用于访问CCD_ 9方法。您可以使用任何UI控件。如果代码驻留在表单中,则可以使用this
。