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アトミックです。これは、コンソールがシェルと対話するように設計されており、シェルの主な目的の1つは、複数のプロセスから入力を収集できるようにすることであるためです。それができるようにするのはかなりの量の作業ですが、現実的にその目的を果たすためにはそれを行う必要がありました。

ラベルなどのGUIオブジェクトは、それを念頭に置いて設計されていません。

于 2012-04-26T12:57:31.360 に答える
0

WinForms では、UI 要素へのすべてのアクセスは専用の UI スレッドで行う必要があります。こちらのセクション 1.2.1 を参照してください。

ドキュメントが言うように:

Exited イベントがボタンなどのビジュアル Windows フォーム コンポーネントによって処理される場合、システム スレッド プールを介したコンポーネントへのアクセスが機能しないか、例外が発生する可能性があります。これを回避するには、SynchronizingObject を Windows フォーム コンポーネントに設定します。これにより、Exited イベントを処理するメソッドが、コンポーネントが作成された同じスレッドで呼び出されます。

于 2012-04-26T12:56:50.610 に答える