还没有需要另一个调用(+后台工作者)

时间:2012-11-04 03:20:52

标签: c# winforms backgroundworker invokerequired

我已经搜索了高低,用于调用堆栈溢出所需的相关帖子..它帮助我学到了很多...但我有几个问题..不仅涉及调用所需,还有背景工作者..忍受我请.. :))

我的应用程序做了很长时间,需要在进程中更新gui(进度条,状态栏,文本框)..我使用了一个线程,但在更新UI时它给出了可怕的跨线程异常..我最近(有点)得到正确使用invokerequired的悬念.. [Automating the InvokeRequired code pattern] ..我在这篇文章中使用的代码是:

public static partial class CHelper
{
    public static void InvokeIfRequired(this Control oCtrl, MethodInvoker fnAction)
    {
        if (oCtrl.InvokeRequired)
        {
            oCtrl.Invoke(fnAction);
        }
        else
        {
            fnAction();
        }
    }
}

public partial class Form1 : Form
{
    public void Test()
    {
        this.InvokeIfRequired(() =>
        {
            Text = "Window Title";
            button1.Text = "Hello";
        });
        button1.InvokeIfRequired(() =>
        {
            Text = "Window Title";
            button1.Text = "Hello";
        });
    }
}

现在这里有一些我注意到的.. this.InvokeIfRequired和button1.InvokeIfRequired都做同样的事情..为什么会这样?我期待button1.InvokeIfRequired中的文本对应于button1的文本属性..但是它引用了父窗体的..对我来说这看起来很傻,不直观,错误......或者可能是我做错了什么......


另一个问题..我当时没有得到invokerequired的挂起所以我使用后台工作者..并使用进度事件来更新gui ..

public partial class Form1 : Form
{
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        backgroundWorker1.ReportProgress(0, "Hello World");
    }
    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        if (e.UserState != null)
        {
            button1.Text = e.UserState as string;
        }
    }
}
到目前为止,它还没有给我带来麻烦..我想知道这两种方法中的哪一种更好?为什么?还有,有没有办法将数据传递给流行的InvokeIfRequired函数?

谢谢.. =)


编辑01:Is there any difference between using Invoke for the parent form or for the target control? ..是form.invoke和control.invoke是一样的......但为什么会这样呢?它不直观,给人错误的印象。

1 个答案:

答案 0 :(得分:0)

嗯,对于Button控件来说根本不重要。 Windows有一个硬规则,即窗口的所有子窗口必须由同一个线程拥有。因此,通过该规则,表单和按钮的Begin / Invoke()方法将封送对正确线程的调用。

请注意,当您需要更新没有Handle属性的组件的属性时,它会变得很尴尬。像ToolStripButton一样。现在你拥有来选择另一个控件。所以赞成一致性并始终使用表格。

当然,请支持BackgroundWorker。它有一个诀窍,可以通过限制你射脚的方式来帮助你做到这一点。