【问题标题】:Enabling panel causes WinForms application to enter "Not Responding " mode启用面板会导致 WinForms 应用程序进入“无响应”模式
【发布时间】:2015-11-06 15:04:21
【问题描述】:

我有一个与DataGridView refresh causes "Not Responding" application (but only when not in Visual Studio) 非常相似的问题

在将数据加载到我的 Winforms 应用程序表单时,我暂时禁用了填充表单并包含所有控件的面板,并在完成后将其重新启用。

与示例一样,我使用 BackgroundWorker 加载数据并使用线程安全的 bgWorkerSend_ProgressChangedbgWorkerSend_RunWorkerCompleted 与 UI 交互。

我还有一个 Windows 窗体计时器,它会在 5 分钟空闲时间后以与窗体相同的方式刷新。

奇怪的是,在初始化加载结束时,面板被正确启用,而在后面的刷新中,应用程序进入“无响应”模式,并永远保持在那里。此外,这只发生在我直接执行应用程序时。如果从 Visual Studio 执行,它在初始加载和刷新时都能正常工作。

private void _bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    if (e.ProgressPercentage == 100)
    {
        // re-enable panel
        panel1.Enabled = true;

        // the below is never reached !!?
        AnyInstruction();
    }
}

【问题讨论】:

  • 这可能是一个跨线程问题,请尝试在 UI 线程上启用面板。
  • 我的理解是_bw_ProgressChanged的内容是在UI线程上执行的,对不对?
  • 只有在正确使用 BGW 时才会出现这种情况。强烈暗示你没有。就像从工作线程而不是 UI 线程调用 RunWorkerAsync() 方法一样。使用 Debug > Windows > Threads 调试器窗口进行验证。
  • 我仔细检查并使用了 VS Debug > Windows > Thread 和 RunWorkerAsync 上的断点,当它停在那里时,它显示它来自主线程,无论是在初始化加载时,还是在刷新时计时器。我假设 Windows 窗体 timer_Tick() 是从主线程执行的。
  • 如果有帮助,实际上_bw.RunWorkerAsync() 是从presenter 类中的事件处理程序启动的,而不是直接从表单类启动的。该事件在演示者和表单(视图)之间关联:_view.DataLoaded += DataLoaded;

标签: c# winforms .net-3.5 backgroundworker


【解决方案1】:

缩小问题范围,它表明问题是因为BackgroundWorker 线程内的代码正在填充一个早先在主线程中实例化的DataSet

通过将实例化移到 BackgroundWorker 线程中,解决了问题,并且 panel1.Enabled = true; 现在在 _bw_ProgressChanged 中正确执行。

【讨论】:

    猜你喜欢
    • 2011-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多