2

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

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

我想知道这样做有什么影响,或者是否有失败的风险?

从许多例子中,我找不到这样的同一件事。

可能是它完全是错误的?

4

2 回答 2

3

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

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

除此之外,您正在做的事情的基本概念非常好。

于 2013-02-21T15:26:26.573 回答
2

这种代码的典型问题:

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

  • 当 UI 关闭并且 pictureBoxHourGlass 被释放时,你会崩溃。在允许 UI 关闭之前确保线程不再运行是很容易被忽视的。仅仅显示一个沙漏是不够的,您还必须采取对策来防止用户关闭 UI。或者以其他方式将其与首先取消线程的方式互锁

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

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

    private void ShowHourGlassSafe(bool visible) {
        this.BeginInvoke(new Action(() => something.Visible = visible));
    }
于 2013-02-21T15:38:34.833 回答