【问题标题】:C# Threading UI for wait dialog等待对话框的 C# 线程 UI
【发布时间】:2011-09-20 18:36:31
【问题描述】:

好的。我环顾四周,试图通过线程化我的 UI 来完成这项工作。

我有一份报告信息的申请。这是如何工作的,我是一个可以在可滚动区域中重复的用户控件。所以如果一天要加载 10 个报告,它将在可滚动区域中加载此控件 20 次。

我想要在加载这些控件时制作一个“请稍候”对话框。但是线程 UI 似乎存在问题,因为 Marquee 模式下的进度条在绘制这些应该位于后面的可滚动区域中的控件时不会动画。

已尝试在后台工作程序中生成控件,但在进度条方面无法解决问题。

在线程化 UI 绘图方面有什么想法或技巧吗? 我想这就是它的样子。绘制其他控件时的进度条。

编辑: 我尝试将这个“请稍候”对话框显示为Show();ShowDialog();。 ShowDialog() 有效,但只是因为它在等待答案时暂停了其余应用程序。

这是生成控件的代码的平静。这不是后台的线程版本。但唯一的区别是“pleaseWait”对话框在代码中的位置。

        /// <summary>
    /// Generates assignemts after date
    /// </summary>
    /// <param name="date">Date for selection of what to show</param>
    /// <param name="currentWeek">Week to show</param>
    /// <param name="igonerWeekCheck">Ignor week check, used for startup</param>
    private void GenerateAssigmentsAfterDate(DateTime date, int currentWeek, bool igonerWeekCheck)
    {
        //refresh UI before generating contens
        tabPage1.Refresh();
        panelScroller.Refresh();
        splitContainer1.Refresh();

        //freezes UI while loading
        SuspendDrawing(splitContainer1);
        panelScroller.SuspendLayout();

        if (CurrentTMEngine.LatestWeekNumber != GetWeekNumber(date) || igonerWeekCheck == true)
        {
            if (igonerWeekCheck == false)
            {
                pleaseWait = PleaseWaitDialog();
                pleaseWait.StartPosition = FormStartPosition.CenterParent;
                pleaseWait.Show();
                pleaseWait.Update();
            }

            //should remove current controls from memory
            int ctrlCount = panelScroller.Controls.Count;
            for (int i = 0; i < ctrlCount; i++)
            {
                panelScroller.Controls[0].Dispose();
            }

            panelScroller.Refresh();

            assignmentList.Clear();
            assignmentList = null;
            assignmentList = new List<messageCtrl>();

            int rowCountCtrl = 0;
            foreach (DataRow row in CurrentTMEngine.TMassignmentsTable.Rows)
            {
                if (currentWeek == GetWeekNumber(Convert.ToDateTime(row[new TableText().TimeStart]).Date))
                {
                    messageCtrl repCtrl = new messageCtrl(rowCountCtrl, Convert.ToInt32(row[new TableText().ID]),
                        Convert.ToDateTime(row[new TableText().TimeStart]), Convert.ToDateTime(row[new TableText().TimeEnd]),
                        panelScroller.Controls, CurrentTMEngine.TMassignmentsTable, row, CurrentTMEngine);
                    assignmentList.Add(repCtrl);//collection to be avalie for show
                    rowCountCtrl++;
                }
            }
            foreach (messageCtrl assign in assignmentList)
            {
                if (currentWeek == GetWeekNumber(assign.StartTime.Date))
                {
                    if (assign.StartTime.Date == date)
                    {
                        assign.Enabled = true;
                        assign.Height = 142;
                        assign.tableLayoutPanel2.BackColor = System.Drawing.SystemColors.ControlLightLight;
                    }
                    else
                    {
                        assign.Enabled = false;
                        assign.Height = 5;
                        assign.tableLayoutPanel2.BackColor = System.Drawing.SystemColors.ControlDark;
                    }
                    panelScroller.Controls.Add(assign); //ands control
                }
            }
            // SetSizeMessageCtrlByDate(date, currentWeek);


            pleaseWait.Close();
            pleaseWait.Dispose();
        }
        else
        {
            SetSizeMessageCtrlByDate(date, currentWeek);
        }
        CurrentTMEngine.LatestWeekNumber = GetWeekNumber(date);

        //unfrezzing UI
        panelScroller.ResumeLayout();
        ResumeDrawing(splitContainer1);
    }
    #endregion

EIDT 2: 似乎与 UI 组件的渲染/绘图有关。当我为控制器扩展这个可滚动区域时,我可以看到这一点,因此它们都适合。应用程序冻结,直到 UI 被重绘为没有滚动条。反之亦然,以使其更小以进行滚动。 这似乎是加载控件时发生的冻结类型。所以我想除非有办法拥有多个 UI 线程,否则可能很难找到解决方案,因为它位于同一个应用程序和这个应用程序 UI 线程中。

目前问题的解决方案是“请稍候”对话框,没有动画选取框滚动条。

将检查是否有办法为此创建一个单独的应用程序来填充这个钱包,因为这似乎是唯一的解决方案。

【问题讨论】:

  • 您的问题可能是每个控件都在 UI 线程上进行底层工作 - 控件是否加载自己的数据,这是在 UI 线程上完成的吗?
  • 如果没有看到您的代码,很难诊断出这个问题。显然,您的代码正在做一些事情来占用 UI 线程。您需要找出那是什么并将其移至后台线程。
  • 在每个生成的控件中都加载了一些数据。但正如我所说,我尝试从后台工作人员生成和应用这些控件。正在加载的这些数据不应该由后台工作人员处理吗?还是因为控件被调用到 UI 标题,所以无论如何它都会获得 UI?
  • 控件有多复杂?延迟可能不是由收集数据引起的,而是控件本身的实际构造和呈现(总是发生在 UI 线程上)。这是在 WinForms 中实例化复杂 UserControls 的多个实例时的常见问题。我建议使用秒表添加一些跟踪代码来对代码的哪一部分花费最多时间进行基准测试。或者,使用性能分析工具(有很多不错的商业产品。)
  • 没那么复杂,但我们不是在这里讨论网格行和单元格:)。所以渲染很可能是个问题

标签: c# multithreading user-interface progressdialog


【解决方案1】:

您可以访问控件的源代码吗?听起来控件正在使用 UI 线程来执行某种后台进程(导致延迟)。不幸的是,只有一个 UI 线程,所以如果它被占用,就会产生停滞效果。

如果您有权访问代码,则可以将其更改为异步加载以避免此问题。如果您无法访问,我能想到的唯一解决方案是启动另一个具有单独 UI 线程的进程(我认为),但这需要创建一个消息框样式窗口。

【讨论】:

  • @Jonas Lindahi - 我很确定 UI 线程不会跨应用程序边界共享。然而,这需要运行一个单独的应用程序来利用这一事实。
猜你喜欢
  • 2016-12-28
  • 1970-01-01
  • 2014-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多