Control.Invoke()挂起应用程序

时间:2011-02-25 15:45:04

标签: c# .net winforms multithreading

当我的控件正在加载数据时,我正在显示动画。线程完成后,我隐藏动画并显示控件。所以我从一个线程执行这段代码:

protected void InvokeEnableBackControl()
{
    if (this.InvokeRequired)
    {                
        this.Invoke(new OpHandler(EnableBackControl));
    }
    else
    {
        EnableBackControl();
    }
}

有时,当我执行此代码时,主线程被挂起在以下代码中:

protected virtual void EnableBackControl()
{
    if (overlayAnimation.TargetControl != null)
    {
        overlayAnimation.TargetControl.BringToFront();
    }

    overlayAnimation.SendToBack();
    overlayAnimation.Enabled = false;
    overlayAnimation.Visible = false;                      

}

我不确定是否挂起设置EnableVisible属性。您是否知道任何情况可能会使应用程序从Control.Invoke调用这些属性?

5 个答案:

答案 0 :(得分:17)

请注意Control.Invoke是同步的,因此会等待EnableBackControl()返回。考虑使用Control.BeginInvoke,您可以“发射并忘记”。

请参阅此答案:What's the difference between Invoke() and BeginInvoke()

答案 1 :(得分:7)

我在执行之前遇到了问题。当主线程仍然忙时,在后台线程上调用 - 这给人的印象是应用程序挂起,因为.Invoke只是坐在那里,等待响应它正在关注的主线程。可能的原因:

  • 您的主要帖子被阻止等待某事
  • 您的主表单目前有一个模态对话框,因此它没有收听新请求
  • 您的主要线程正在旋转,要么不断检查某些内容是否已完成,或是否正在开展新工作。在我的情况下,主线程花了第一分钟在紧密循环中旋转后台线程,因此它没有侦听来自后台线程的任何.Invoke请求。

当您附加调试器时,请特别注意您的主控制MessagePump线程正在做什么 - 我怀疑它缺乏关注是您的麻烦的原因。如果您确定主线程中的响应循环没有响应,请尝试在循环中插入.DoEvents,这将暂停执行并强制主线程清空消息泵并路由任何未完成的请求。

答案 2 :(得分:4)

在debug中运行,make app hang,然后在Visual Studio中暂停调试并检查线程。

答案 3 :(得分:0)

我发现控制的实际绘制/绘制可能非常慢,特别是如果你有很多这样的和/或使用双缓冲来平滑刷新。我正在使用BeginInvoke从我从套接字接收的数据更新listview控件。有时更新发生得如此之快,以至于冻结了应用程序。我通过将套接字异步接收中收到的所有内容写入队列,然后在单独的线程中将数据出列并在列表视图上使用 BeginUpdate EndUpdate 进行解决,从而解决了这个问题。所有未完成的更新。这减少了大量的额外重绘,使应用程序响应更快。

答案 4 :(得分:0)

您必须使用BeginInvoke inested Invoke查看此Link