gpt4 book ai didi

c# - 报告异步任务的进度

转载 作者:行者123 更新时间:2023-11-30 14:24:12 26 4
gpt4 key购买 nike

各位开发者大家好,

我正面临一个小小的困境。我有一个 WPF 应用程序,它读取一个相当大的 Excel 文件,然后将其输出为 XML 文件。我面临的问题是我想将操作的进度报告回处理程序。

我无法让它“顺利地”工作,字面意思是 GUI 线程中的进度条立即被填满,然后保存从 Excel 文件读取的内容的 DataGrid 被填满。

我是 Async/Await/Task 的新手,我一直在使用 BackgroundWorker 直到现在,但我希望获得更多这方面的知识,所以如果这是一个愚蠢的问题,我很抱歉。

我已经从 here. 阅读了 Stephen Cleary 的教程

老实说,我不知道为什么进度条没有像它应该的那样“顺利”填充......

在 GUI 中被调用的代码:

        var progress = new Progress<int>(progressPercent => pBar.Value = progressPercent);

Task.Run(() => _sourceService.ReadFileContent(filePath, progress)).ContinueWith(task =>
{

dataGrid.ItemsSource = task.Result.DefaultView;
DataTable = task.Result;

if (DataTable.Rows.Count > 0)
BtnCreateXmlFile.IsEnabled = true;

}, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());

ReadFileContent(filePath, progress)方法体:

public DataTable ReadFileContent(string filePath, IProgress<int> progress)
{
var rowStart = 7;
var columnStart = 1;

var existingFile = new FileInfo(filePath);
using (var package = new ExcelPackage(existingFile))
{
var worksheet = package.Workbook.Worksheets["BOP"];
var dt = new DataTable();

// Compose the name of the table from:
// - Product Type
// - Customer
// - Customer Project
// * These can be found in the "CollaborationContext" sheet that is present in the ExcelFile.
if (package.Workbook.Worksheets["CollaborationContext"].SelectedRange["B6"].Value.Equals("object_type"))
{
dt.TableName = package.Workbook.Worksheets["CollaborationContext"].SelectedRange["C9"].Value + " " +
package.Workbook.Worksheets["CollaborationContext"].SelectedRange["D9"].Value + " " +
package.Workbook.Worksheets["CollaborationContext"].SelectedRange["E9"].Value;
}


dt.TableName = package.Workbook.Worksheets["CollaborationContext"].SelectedRange["B9"].Value + " " +
package.Workbook.Worksheets["CollaborationContext"].SelectedRange["C9"].Value + " " +
package.Workbook.Worksheets["CollaborationContext"].SelectedRange["D9"].Value;


// Report only in chunks. We do not want to call `progress.Report` for each row that is read.
var totalRows = worksheet.Dimension.End.Row;
var currentIndex = 0;
var percentageProgress = totalRows / 10;


// Get Columns and add them to the DataTable
for (var col = columnStart; col <= worksheet.Dimension.End.Column - 1; col++)
dt.Columns.Add(worksheet.Cells[6, col].Value.ToString());

// Place data into DataTable
for (var row = rowStart; row <= worksheet.Dimension.End.Row; row++)
{
var dr = dt.NewRow();
var x = 0;
currentIndex++;

for (var col = columnStart; col <= worksheet.Dimension.End.Column - 1; col++)
{
dr[x++] = worksheet.Cells[row, col].Value;
}
dt.Rows.Add(dr);

// Report progress back to the handler
if (currentIndex % percentageProgress == 0)
progress?.Report(row);
}

return dt;
}

}

提前致谢!

最佳答案

首先,让我们摆脱危险的ContinueWith称呼。你真的应该使用 await相反:

var progress = new Progress<int>(progressPercent => pBar.Value = progressPercent);
var result = await Task.Run(() => _sourceService.ReadFileContent(filePath, progress));
dataGrid.ItemsSource = result.DefaultView;
DataTable = result;
if (DataTable.Rows.Count > 0)
BtnCreateXmlFile.IsEnabled = true;

接下来,您可能会看到的问题是您的 Progress<int>处理程序期待 progressPercent ,但是 ReadFileContent发送的是读取的行数,不是百分比。所以,要解决这个问题:

if (currentIndex % percentageProgress == 0)
progress?.Report(row * 100 / totalRows);

(这里还有其他几个选项;例如,如果您想要更漂亮的 UI,您可以决定报告当前行总行数)。

the Progress Bar does not fill "smoothly" as it should be

我上面描述的是最低可接受的解决方案。特别是“只更新10次”的代码有点问题;它总是更新 10 次,无论更新的速度有多快或多慢。更通用的解决方案是使用基于 Rx 的 IProgress解决方案,它允许您根据时间进行节流(例如,每秒 4 次更新)。

关于c# - 报告异步任务的进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41961070/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com