4

私の GUI コードでは、次のように書くことがよくあります。

private void SecondTimer_Elapsed(object sender, ElapsedEventArgs e)
{
    if (progressBar1.InvokeRequired)
    {
      progressBar1.BeginInvoke(new ElapsedEventHandler(SecondTimer_Elapsed), new[] {sender, e});
      return;
    }
//Code goes here
}

もちろん、最初にコントロールを作成したスレッドをマーシャリングする必要があるため、アプリがマルチスレッドの場合はこれが必要です。問題は、デリゲートを記述して引数を配列に入れるのは面倒な場合があり、そのようなすべてのイベント ハンドラーの上部でスペースを占有することです。このコードを置き換える属性またはそれらの行に沿ったものはありますか? 基本的に、「間違ったスレッドにいる場合は、同じ引数で GUI スレッドにもう一度電話してください」というラベルです。

4

3 に答える 3

13

私はそのようなものをまったく知りませんが、これはおそらくあなたにとって便利な拡張メソッドになるでしょう:

public static class Extensions
{
    public static void Execute(this ISynchronizeInvoke invoker,
                               MethodInvoker action)
    {
        if (invoker.InvokeRequired)
        {
             invoker.BeginInvoke(action);
        }
        else
        {
             action();
        }
    }
}

もちろん、これはパラメーターなしのデリゲートに対してのみ機能します...しかし、ラムダ式では問題になる必要はありません。

progressBar1.Execute(() => SecondTimer_Elapsed(sender, e));

これには次の利点があります。

  • 書き方は簡単です
  • 署名を間違えることはありません(遅延バインディングに依存していません)
  • MethodInvoker他のデリゲートよりもわずかに効率的に実行されると思います
  • 実行するコードがあまりない場合は、ラムダ式でインラインで記述できます
于 2010-08-15T20:55:32.683 に答える
3

拡張メソッドでこれを整理できます。

// Extension methods.
public static void BeginInvoke(this ISynchronizeInvoke @this, MethodInvoker action) {
    if (@this.InvokeRequired) @this.BeginInvoke(action);
    else action();
}

public static void BeginInvoke<T1, T2>(this ISynchronizeInvoke @this, Action<T1, T2> action, T1 arg1, T2 arg2) {
    if (@this.InvokeRequired) @this.BeginInvoke(action, new object[] { arg1, arg2 });
    else action(arg1, arg2);
}

// Code elsewhere.
progressBar1.BeginInvoke(() => SecondTimer_Elapsed(sender, e));
// Or:
progressBar1.BeginInvoke(SecondTimer_Elapsed, sender, e);

編集: MethodInvoker デリゲートを使用する方が高速であるという Jon Skeet の発言は正しいです。MSDNから:

EventHandlerまたはデリゲートへのMethodInvoker呼び出しは、別の種類のデリゲートへの呼び出しよりも高速です。

于 2010-08-15T21:01:39.070 に答える
0

このためのAOP フレームワークを入手してください。MethodInterceptionAspect関数が呼び出されたときに起動するを作成できます。次に、チェックを実行して、関数 (関数への参照とその引数がある) を GUI スレッドに投げるか、直接実行します。

利点は、このコードを 1 回記述する必要があり、属性だけで必要なすべてのプロパティに適用できることです。

于 2010-08-15T20:56:22.203 に答える