3

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

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;才能工作。为什么它们应该不同?

4

2 回答 2

6

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

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

于 2012-04-26T12:57:31.360 回答
0

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

正如文档所说:

当 Exited 事件由可视化 Windows 窗体组件(例如 Button)处理时,通过系统线程池访问组件可能不起作用,或者可能导致异常。通过将 SynchronizingObject 设置为 Windows 窗体组件来避免这种情况,这会导致在创建组件的同一线程上调用处理 Exited 事件的方法。

于 2012-04-26T12:56:50.610 回答