使用EventHandler更新主线程中的控件

时间:2013-02-21 15:22:01

标签: c# visual-studio-2008 event-handling thread-safety compact-framework2.0

我正在使用它从另一个线程更新主线程中的控件:

private void ShowHourGlassSafe(bool visible)
{
    this.Invoke((EventHandler)((s, ev) => pictureBoxHourGlass.Visible = visible));           
}

我想知道这样做会带来什么影响,或者是否有任何风险会失败?

从很多例子来看,我找不到像这样的东西。

可能是因为它完全错了?

2 个答案:

答案 0 :(得分:3)

嗯,你已经选择了一个相当奇怪的代表来选择,因为你已经选择了一个有两个参数的代表,尽管事实上既不需要也不会提供。我不知道这是否会导致它破裂,但它肯定无济于事。您最有可能使用不带参数的委托并且不返回任何值,例如:

private void ShowHourGlassSafe(bool visible)
{
    this.Invoke((MethodInvoker)(() => pictureBoxHourGlass.Visible = visible));           
}

除此之外,你所做的基本概念非常好。

答案 1 :(得分:2)

此类代码存在典型问题:

  • 如果UI线程正在做一些不明智的事情,比如等待线程完成,你就会死锁。使用Invoke是没有意义的,它阻止工作线程没有任何好处,只需使用BeginInvoke。解决死锁潜力和不必要的延迟。

  • 关闭用户界面并处理pictureBoxHourGlass后,您将崩溃。在允许UI关闭之前确保线程不再运行通常被忽视。仅显示小时玻璃是不够的,您还必须采取对策以防止用户关闭UI。或以其他方式将其与首先取消线程的方式联系起来

  • 当一小时玻璃出现时,用户通常会被迷惑,而他没有做任何事情要求完成任务。 99%正确的情况是你在UI线程中显示带有代码的沙漏,然后启动线程。并在线程完成时再次隐藏它。使用BackgroundWorker或Task类最容易,它们可以在作业完成后在UI线程上运行代码。

支持Action委托类型以保持一致性:

    private void ShowHourGlassSafe(bool visible) {
        this.BeginInvoke(new Action(() => something.Visible = visible));
    }