与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;
才能工作。为什么它们应该有所不同?
Console
类是故意编写的,目的是线程安全的。 您可以从任何线程调用它。 它甚至会确保不会"重叠"来自不同线程的调用。 Console.Write/WriteLine
是原子的。 这是因为控制台旨在与 shell 交互,而 shell 的一个主要目的是能够从多个进程收集输入。 让它能够做到这一点是相当多的工作,但它需要做才能真正达到它的目的。
GUI 对象(如标签)在设计时并未考虑到这一点。
在 WinForms 中,对 UI 元素的所有访问都必须在专用 UI 线程上。请参阅此处的第 1.2.1 节。
正如文档所说:
当 Exited 事件由可视 Windows 窗体组件处理时, 例如按钮,通过系统线程访问组件 池可能不起作用,或者可能导致异常。通过以下方式避免这种情况 将同步对象设置为 Windows 窗体组件,这会导致 处理要在同一线程上调用的 Exited 事件的方法 在其上创建组件。