0

我正在用 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() 从节点指向的文件中读取文本并将其显示在富文本框中。

执行后,我的主窗体仍然可以按我的意愿使用,但是当进程终止(记事本关闭)时,它会抛出一个错误,指出函数 NotePadHasEnded 无法访问 treeView1 对象,因为它正在另一个进程中执行。

如何创建一个在我的主窗体中异步退出时调用函数的进程?我知道当我使用 WaitForExit() 函数时它可以工作,但是我的表单会冻结并等到记事本关闭。我希望用户能够使用编辑器打开其他 txt 文件,并且当关闭一个编辑器时,我的 GUI 中的富文本框文本正在更新。

/编辑/ 现已解决。感谢伍德曼的回答,我更换了

            editor.Exited += delegate {
            NotePadHasEnded(node);
            };

  editor.Exited += delegate
        {
            this.Invoke((MethodInvoker)delegate()
            {
                NotePadHasEnded(node);
            });
        };
4

3 回答 3

0

您应该使用Dispatcher.Invokeor Dispatcher.BeginInvokeinsideNotePadHasEnded()方法切换到 UI 线程,因为您只允许从 UI 线程访问 UI 对象。

查看此帖子以获取更多详细信息。

于 2013-02-23T14:15:53.337 回答
0

谷歌同步上下文。发生错误是因为您的 UI 线程未与运行的第二个线程同步,然后编辑器被关闭。我找到了一些描述如何实现同步的示例:这都是关于 SynchronizationContextExecutionContext 与 SynchronizationContext的。希望这可以帮助你;-)

于 2013-02-23T14:16:36.063 回答
0

Exited事件发生在另一个线程中,您只能在自己的线程(称为UI线程)中访问UI控件。由于您使用的是 Windows 窗体,因此您应该使用以下Control.Invoke方法:

editor.Exited += delegate
{
    node.TreeView.Invoke(new Action<TreeNode>(NotePadHasEnded), node);
};

还将返回类型更改NotePadHasEndedvoid

node.TreeView用于访问Invoke方法。您可以使用任何 UI 控件。如果代码驻留在表单中,则可以this改用。

于 2013-02-23T14:30:17.603 回答