0

昨天我有一个问题困扰了我好几个小时。在我的程序的某个时刻,另一个线程更改了表单上的控件(例如可见性和加载图像)。不抛出异常 ( checkforillegalcrossthread...=false)。application.doevent()但是,在调用之前,更改不适用。如果这还不够,如果application.doevent()没有调用,应用程序就会挂起!

我的第一个猜测(你可能也是)是 UI 线程(主线程)很忙,但事实并非如此。它没有任何代码要运行,它在调试期间不运行任何东西,它只是卡在了Application.run(..)线上,但是它是创建控件的线程。

任何想法是什么问题?

阅读答案后,我宁愿重新提出我的问题。我怎么知道我的主线程是否确实空闲?我通常做的是在调试期间暂停所有其他线程,切换到我的主线程并查看下一条指令。如果我移动一个步骤时没有任何反应,那么它是空闲的。还有其他方法吗?

4

1 回答 1

0

这可能是由于试图从不同的线程更改控件造成的。

您可以通过使用Control.BeginInvoke()Control.Invoke()运行更新控件的代码来更正它。

例如,SetLabel()从单独的线程调用此方法是安全的。它检查Control.InvokeRequired这是否是从 UI 线程以外的线程调用的。如果是,它用于BeginInvoke()将委托传递给 UI 线程以执行。

委托采用 lambda 表达式的形式() => label1.Text = text,它只是设置标签的文本。它必须包装在Action()委托中才能与BeginInvoke().

public void SetLabel(string text)
{
    if (this.InvokeRequired)
    {
        this.BeginInvoke(new Action(() => label1.Text = text));
    }
    else
    {
        label1.Text = text;
    }
}

通常最好使用BeginInvoke()而不是Invoke() 尽可能使用,因为它大大减少了死锁的机会。

有关这方面的有趣讨论,请参阅此博客

于 2013-04-11T18:20:48.580 回答