【发布时间】: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