2

public Event を公開するクラスがあります。GUI にはさまざまなコントロールがあり、イベント ハンドラーをこのイベントに登録して、テキストや背景色などのコントロールに変更を加えることができます。ただし、イベントを公開するクラスは、それらが持つ可能性のある UI コントロールの参照を保持しません。イベント ハンドラを追加しました。

実行中、別のフォアグラウンド スレッドが、パブリック イベントを呼び出す (起動する) メソッドを実行します。これにより、イベントに登録されているイベント ハンドラーが呼び出されます。

問題は、イベント ハンドラーが UI スレッドではなくフォアグラウンド スレッドで呼び出されることです。UI コントロールを参照せずに UI スレッドへの呼び出しをマーシャリングするにはどうすればよいですか?

4

3 に答える 3

3

イベント呼び出しを(一意の)UIスレッドにマーシャリングすることが懸念される場合は、ISynchronizeInvoke必要なのはそれだけです。

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    Form mainForm = new MyForm();

    // Initialize the service.
    MyService service = new MyService(mainForm);

    Application.Run(mainForm);
}


public class MyService
{
    public event EventHandler MyEvent;

    private readonly ISynchronizeInvoke synchronizeInvoke;

    public MyService(ISynchronizeInvoke synchronizeInvoke)
    {
        this.synchronizeInvoke = synchronizeInvoke;
    }

    private void OnMyEvent()
    {
        if (MyEvent != null)
        {
            if (synchronizeInvoke.InvokeRequired)
            {
                synchronizeInvoke.BeginInvoke(new Action(() => MyEvent(this, EventArgs.Empty)), null);
            }
            else
            {
                MyEvent(this, EventArgs.Empty);
            }
        }
    }
}
于 2012-08-05T08:41:24.267 に答える
3

マーシャリングを行うものを決定する必要があります: イベント レイザーまたはイベント ハンドラーです。イベント レイザーにスレッドについて何も認識させたくない場合 (たとえばISynchronizeInvokeorを介して) SynchronizationContext、代わりにイベント ハンドラーにマーシャリングを実行させます。

基本的に、イベント レイザーは、特定のコンテキストですべてのイベントを発生させることを保証する必要があります (これは、 を介して構築時に指定できます)、そうでないSynchronizationContextことを明確にして、ハンドラーに責任を負わせる必要があります。後者はより柔軟なアプローチです。これは、異なるニーズを持つ複数のハンドラーがある場合、それぞれが独自のニーズに合わせて適切な処理を実行できることを意味します。

于 2012-08-05T08:07:36.097 に答える
2

Application.OpenForms() を使用して、開いているフォームを取得できます。

Form form = System.Windows.Forms.Application.OpenForms().FirstOrDefault();
if (form != null)
    form.Invoke((MethodInvoker)delegate(){ event(); });
于 2012-08-05T08:11:58.373 に答える