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

本文关键字:窗体 函数 调用 然后 进程 结束 异步 等待 | 更新日期: 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.InvokeDispatcher.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