如何编写PostSharp Invoke方面以简化跨线程控制更新

Bra*_*ore 3 c# multithreading postsharp winforms

当我想跨线程更新控件时,我通常最终会这样做:

this.Invoke((MethodInvoker)delegate { SomeProcedure(); });
Run Code Online (Sandbox Code Playgroud)

建议的方法实际上是调用调用者来获取你想要更新的特定控件,但99%的时候表单(即我的例子中的'this')和控件都将在同一个控件上创建线程所以我真的很喜欢这样做,为了简单起见.

我在想,如果我只是将PostSharp方面置于SomeProcedure之上,将它包含在我的那个混乱的声明中,那将是很好的.

然后去......(哦是啊,第一个可用的答案100奖金:)

Chr*_*air 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

这个想法是在你的应用程序的开始,用属性注册你的主/根控件.然后你想要确保的任何方法都在主线程上运行,只需装饰[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();
    }
}
Run Code Online (Sandbox Code Playgroud)