【问题标题】:How to avoid DevExpress Spreadsheet freeze while doing heavy calculations?在进行大量计算时如何避免 DevExpress 电子表格冻结?
【发布时间】:2021-02-12 11:36:49
【问题描述】:

我在自己的项目中使用 DevExpress 电子表格。我在功能区中创建了一个按钮,用于对单元格进行一些计算。它从工作表的单元格获取信息并创建一个新工作表,并将计算结果写入其行和单元格。这些计算是在超过 5000 行中完成的。 UI 冻结大约 10 秒。我不想使用进度条,但我会使用 DevExpress 附带的进度动画(它被称为进度面板,就像 Windows 10 加载点)。 我尝试使用 BackGroundWorker 来避免 UI 冻结。由于我的操作的跨线程性质(创建工作表,在单元格中写入数据......)我不能直接在 DoWork 部分使用它们。所以,我使用调用和委托。但是我的 UI 和进度动画在处理过程中仍然没有响应。

       private void barButtonItem5_ItemClick(object sender, ItemClickEventArgs e)
    {
        if (!backgroundWorker1.IsBusy)
        {
            backgroundWorker1.RunWorkerAsync();
        }
    }
  
    private void FillCell(string _sheetName)
    {
        IWorkbook workbook = spreadsheetControl.Document;
        Worksheet worksheet = workbook.Worksheets["DataSet1"];
        CellRange range = worksheet.GetDataRange();
        int LastRow = range.BottomRowIndex;
        var keys = new List<string>();
        var values = new List<int>();

        for (int i = 0; i < LastRow + 1; i++)
        {
            if (worksheet.Cells[i, 10].DisplayText == "خاتمه یافته")
            {
                keys.Add(string.Join(",", worksheet.Cells[i, 28].DisplayText, worksheet.Cells[i, 0].DisplayText, worksheet.Cells[i, 9].DisplayText,
                worksheet.Cells[i, 15].DisplayText, worksheet.Cells[i, 31].DisplayText));
                values.Add((int)worksheet.Cells[i, 32].Value.NumericValue);
            }
        }
        var mydic = new Dictionary<string, int>();
        for (int i = 0; i < keys.Count; i++)
        {
            if (mydic.ContainsKey(keys[i]))
            {
                mydic[keys[i]] += values[i];
            }
            else
            {
                mydic.Add(keys[i], values[i]);
            }
        }
        foreach (var item in mydic.Keys)
        {
            keys.Add(item);
        }
        foreach (var item in mydic.Values)
        {
            values.Add(item);
        }

        for (int i = 0; i < mydic.Count; i++)
        {
            string text = keys[i];
            string[] rewrite = text.Split(',');

            workbook.Worksheets[_sheetName].Cells[i, 0].SetValue(rewrite[0]);
            workbook.Worksheets[_sheetName].Cells[i, 1].SetValue(rewrite[1]);
            workbook.Worksheets[_sheetName].Cells[i, 2].SetValue(rewrite[2]);
            workbook.Worksheets[_sheetName].Cells[i, 3].SetValue(rewrite[3]);
            workbook.Worksheets[_sheetName].Cells[i, 4].SetValue(rewrite[4]);
        }
        for (int i = 0; i < mydic.Count; i++)
        {
            int text = values[i];

            workbook.Worksheets[_sheetName].Cells[i, 5].SetValue(text);
        }
    }

    private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        
        IWorkbook workbook = spreadsheetControl.Document;
        Worksheet worksheet = workbook.Worksheets["DataSet1"];

        if (worksheet.HasData)
        {
            if (spreadsheetBarController1.Control.InvokeRequired)
            {
                //***Instead of (Action), we can use (MethodInvoker)***
                spreadsheetBarController1.Control.Invoke((Action)delegate { CreateSheet("Summarized"); });
                spreadsheetBarController1.Control.Invoke((MethodInvoker)delegate { ClearSheet("Summarized"); });
                spreadsheetBarController1.Control.Invoke((Action)delegate { FillCell("Summarized"); });
            }
        }
        else
        {
            MessageBox.Show("خطای داده ورودی", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
    {
        progressPanel1.Visible = false;
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressPanel1.Visible = true;
    }
}

【问题讨论】:

  • 以下哪种方法会阻止您?代码太多了。在您的问题中了解how to create an example
  • 方法 FillCell 对 UI 冻结的影响最大。我从我的问题中删除了其他方法。
  • 你检查过异步等待模式吗?
  • 原因是我的很多计算都与 UI 有关,例如,创建工作表、清除工作表和用数据填充单元格。我不知道如何管理它们以避免 UI 冻结。

标签: c# devexpress backgroundworker spreadsheet


【解决方案1】:

首先尝试在FillCell 方法的开头使用workbook.BeginUpdate() 来抑制SpreadsheetControl 的视觉更新,并在对电子表格文档执行多项更改时提高其性能。也可以在FillCell 方法末尾使用workbook.EndUpdate() 来解锁控件并使所有更改生效。

【讨论】:

    【解决方案2】:

    我使用了 DevExpress.Docs 程序集,它的工作速度比手动填充单元格快得多。我的计算数据被放入 DataTable 中,然后在不到一秒的时间内被带到单元格中。

    【讨论】:

      猜你喜欢
      • 2023-03-26
      • 2021-11-19
      • 2012-06-27
      • 1970-01-01
      • 2018-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多