与Winform相比,控制台的流程

本文关键字:控制台 Winform 相比 | 更新日期: 2023-09-27 18:32:30

以下控制台应用程序运行正常 - 我很惊讶它没有错误。

class DelegateExperiments
{
    //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    //open notepad when the console begins
    //create an event that fires and writes "Notepad closed" in the console
    //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    //instance variables of the form
    private const string helloText = "hello world";
    private const string exitText = "you just closed notepad";
    private Process myProcess;
    //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<        

    static void Main(string[] args)
    {
        Console.WriteLine(helloText);
        DelegateExperiments myInstance;
        myInstance = new DelegateExperiments();
        myInstance.Foo();
        Console.Read();
    }
    void Foo()
    {
        myProcess = new Process();
        myProcess.StartInfo.FileName = @"notepad.exe";
        myProcess.Exited += MyProcessExited;
        myProcess.EnableRaisingEvents = true;
        //myProcess.SynchronizingObject = this;
        myProcess.Start();
    }
    private void MyProcessExited(Object source, EventArgs e)
    {
        Console.WriteLine(exitText);
    }

}

如果我尝试使用 winform 做类似的事情,即将消息写回表单上的标签,那么它会更复杂,需要行myProcess.SynchronizingObject = this;才能工作。为什么它们应该有所不同?

与Winform相比,控制台的流程

Console类是故意编写的,目的是线程安全的。 您可以从任何线程调用它。 它甚至会确保不会"重叠"来自不同线程的调用。 Console.Write/WriteLine是原子的。 这是因为控制台旨在与 shell 交互,而 shell 的一个主要目的是能够从多个进程收集输入。 让它能够做到这一点是相当多的工作,但它需要做才能真正达到它的目的。

GUI 对象(如标签)在设计时并未考虑到这一点。

在 WinForms 中,对 UI 元素的所有访问都必须在专用 UI 线程上。请参阅此处的第 1.2.1 节。

正如文档所说:

当 Exited 事件由可视 Windows 窗体组件处理时, 例如按钮,通过系统线程访问组件 池可能不起作用,或者可能导致异常。通过以下方式避免这种情况 将同步对象设置为 Windows 窗体组件,这会导致 处理要在同一线程上调用的 Exited 事件的方法 在其上创建组件。