3

スレッド間でコントロールを更新したい場合、これは一般的に次のようになります。

this.Invoke((MethodInvoker)delegate { SomeProcedure(); });

推奨される方法は、実際には、更新する特定のコントロールの呼び出し元を呼び出すことですが、99% の時間で、フォーム (つまり、私の例では「これ」) とコントロールは同じ上に作成されます。スレッドなので、単純にするためにこのようにするのが本当に好きです。

私は、PostSharp の側面を SomeProcedure の上に置いて、その混乱したステートメントにラップするだけでいいと思っていました。

そして行く...(そうそう、最初の使用可能な答えに100ボーナスポイント:)

4

1 に答える 1

8

WinForms でスレッド アクセスをプログラミングしたことはありませんが、PostSharp + Silverlight でプログラミングしました。少しグーグルで検索してみます。ただし、動作することを保証するものではありません!

[Serializable]
public class OnGuiThreadAttribute : MethodInterceptionAspect
{
    private static Control MainControl;

    //or internal visibility if you prefer
    public static void RegisterMainControl(Control mainControl) 
    {
        MainControl = mainControl;
    }

    public override void OnInvoke(MethodInterceptionArgs eventArgs)
    {
        if (MainControl.InvokeRequired)
            MainControl.BeginInvoke(eventArgs.Proceed);
        else
            eventArgs.Proceed();
    }
}

そして、アイデアはアプリケーションの開始時にあり、メイン/ルートコントロールを属性に登録します。次に、確実にメインスレッドで実行したいメソッドを でデコレートし[OnGuiThread]ます。すでにメイン スレッド上にある場合は、メソッドを実行するだけです。そうでない場合は、メソッド呼び出しをメイン スレッドへのデリゲートとして非同期的に昇格させます。

編集: 使用しているターゲット コントロールに特定の呼び出しメソッドを使用するように求めていることがわかりました (遅いです)。コントロールのサブクラスでインスタンスメソッドをデコレートすると仮定します。

[Serializable]
public class OnGuiThreadAttribute : MethodInterceptionAspect
{
    public override void OnInvoke(MethodInterceptionArgs eventArgs)
    {
        //you may want to change this line to more gracefully check 
        //if "Instance" is a Control
        Control targetControl = (Control)eventArgs.Instance;

        if (targetControl.InvokeRequired)
            targetControl.BeginInvoke(eventArgs.Proceed);
        else
            eventArgs.Proceed();
    }
}
于 2012-06-25T03:37:02.900 に答える