在Control.Invoke期间需要设置多个属性

时间:2009-08-23 21:29:04

标签: c# invoke

我一直在搜索stackoverflow,以便将数据从一个线程编组回到UI线程,并在3.5中找到了各种方法。

对我来说更优雅的解决方案之一;虽然我还在学习lambdas和闭包,但这个解决方案是Control.Invoke with input Parameters

我不完全理解代码,但我确实理解如何使用它并且它并没有完全解决我的问题。

我想调用invoke并将字符串传递给另一个方法(DisplayStatusUpdate(msg))。任何指针都会受到赞赏。

    private void FireEventAppender_OnMessageLogged(object sender, MessageLoggedEventArgs e)
    {
        DisplayStatusUpdate(e.LoggingEvent.RenderedMessage);
    }

    private void DisplayStatusUpdate(string text)
    {
         _StatusTextBox.Text = _StatusTextBox.Text + text;
         _StatusTextBox.Text = String.Format("{0}\r\n", _StatusTextBox.Text);
         _StatusTextBox.SelectionStart = _StatusTextBox.Text.Length - 1;
         _StatusTextBox.ScrollToCaret();
    }

2 个答案:

答案 0 :(得分:5)

您可以使用任意数量的参数执行此操作,例如:

private void FireEventAppender_OnMessageLogged(object sender, MessageLoggedEventArgs e)
{
    DisplayStatusUpdate(e.LoggingEvent.RenderedMessage);
}

private delegate void DisplayStatusUpdateDelegate(string text);

private void DisplayStatusUpdate(string text)
{
     if(InvokeRequired)
         this.Invoke(new DisplayStatusUpdateDelegate(DisplayStatusUpdate), text);
     else
     {
         _StatusTextBox.Text = _StatusTextBox.Text + text;
         _StatusTextBox.Text = String.Format("{0}\r\n", _StatusTextBox.Text);
         _StatusTextBox.SelectionStart = _StatusTextBox.Text.Length - 1;
         _StatusTextBox.ScrollToCaret();
     }
}

我在当前项目中使用的另一种方法可以显着减少代码。详细信息为here

如果您实施此方法,则需要:

使用AOP工厂创建表单:

Form f = AOPFactory.Create<Form1>();
Application.Run(f);

然后你只需用[RunInUIThread]属性装饰事件处理程序。它使用Castle的方法拦截模型在需要时自动调用。

因此,上面的代码变为:

private void FireEventAppender_OnMessageLogged(object sender, MessageLoggedEventArgs e)
{
    _StatusTextBox.Text = _StatusTextBox.Text + text;
    _StatusTextBox.Text = String.Format("{0}\r\n", _StatusTextBox.Text);
    _StatusTextBox.SelectionStart = _StatusTextBox.Text.Length - 1;
    _StatusTextBox.ScrollToCaret();
}

性能方面,它似乎具有可比性,稍慢,但取决于你正在做什么它可能没问题,它肯定需要更少的代码。

答案 1 :(得分:2)

如果您使用的是C#3.5(或更高版本),则可以使用捕获的变量,这可能会简化代码:

private void DisplayStatusUpdate(string text)
{
    this.Invoke(new MethodInvoker(() => 
    {
         _StatusTextBox.Text = _StatusTextBox.Text + text;
         _StatusTextBox.Text = String.Format("{0}\r\n", _StatusTextBox.Text);
         _StatusTextBox.SelectionStart = _StatusTextBox.Text.Length - 1;
         _StatusTextBox.ScrollToCaret();
    }));
}

编译器将在幕后执行的操作是生成一个类来保存文本,创建MethodInvoker委托,并将该委托和生成的类的实例传递给Invoke方法。在上面的设计中,这当然会做一些不必要的工作,即创建一个委托并调用Invoke,即使代码已经在同一个线程上运行了;但是我认为这样的方法通常不会被称为性能问题。

如果您愿意,可以使用无参数Action委托或任何其他返回void的无参数委托替换MethodInvoker的使用。