以下控制台应用程序运行正常 - 我很惊讶它没有错误。
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;
才能工作。为什么他们会有所不同?
答案 0 :(得分:6)
有意将Console
类编写为线程安全的。你可以从任何线程调用它。它甚至可以确保不会“重叠”来自不同线程的调用。 Console.Write/WriteLine
是原子的。这是因为Console旨在与shell交互,而shell的一个主要目的是能够从多个进程收集输入。能够做到这一点是一项相当大的工作,但需要做到这一点才能真正实现其目的。
GUI对象(例如标签)的设计没有考虑到这一点。
答案 1 :(得分:0)
在WinForms中,对UI元素的所有访问都必须位于专用UI线程上。请参阅第1.2.1节here。
正如文件所说:
当可视Windows窗体组件处理Exited事件时, 例如Button,通过系统线程访问组件 池可能不起作用,或者可能导致异常。避免这样做 将SynchronizingObject设置为Windows窗体组件,这会导致 处理在同一线程上调用的Exited事件的方法 在哪个组件上创建。