我有一个WinForms应用程序,其中包含按钮和RichTextBox控件。用户单击按钮后,将执行IO操作。为了防止UI线程被阻塞,我已经实现了异步/等待模式。我还希望将此操作的进度报告到RichTextBox中。这是简化逻辑的样子:
private async void LoadData_Click(Object sender, EventArgs e)
{
this.LoadDataBtn.Enabled = false;
IProgress<String> progressHandler = new Progress<String>(p => this.Log(p));
this.Log("Initiating work...");
List<Int32> result = await this.HeavyIO(new List<Int32> { 1, 2, 3 }, progressHandler);
this.Log("Done!");
this.LoadDataBtn.Enabled = true;
}
private async Task<List<Int32>> HeavyIO(List<Int32> ids, IProgress<String> progress)
{
List<Int32> result = new List<Int32>();
foreach (Int32 id in ids)
{
progress?.Report("Downloading data for " + id);
await Task.Delay(500); // Assume that data is downloaded from the web here.
progress?.Report("Data loaded successfully for " + id);
Int32 x = id + 1; // Assume some lightweight processing based on downloaded data.
progress?.Report("Processing succeeded for " + id);
result.Add(x);
}
return result;
}
private void Log(String message)
{
message += Environment.NewLine;
this.RichTextBox.AppendText(message);
Console.Write(message);
}
操作成功完成后,RichTextBox 中包含以下文本:
Initiating work...
Downloading data for 1
Data loaded successfully for 1
Processing succeeded for 1
Downloading data for 2
Data loaded successfully for 2
Processing succeeded for 2
Downloading data for 3
Done!
Data loaded successfully for 3
Processing succeeded for 3
正如您所看到的,第三个工作项的进度报告是在Done!
之后报告的。
我的问题是,是什么原因导致了延迟的进度报告,我该如何实现LoadData_Click
的流程只有在所有进度报告完成后才会继续?
IProgress<String>
和Progress
?它们的来源在哪里?它们似乎对你的问题非常重要。 - Enigmativityprogress?.Report(
将p => this.Log(p)
的执行推到了SychronizationContext
上。这意味着它必须等待 UI 消息循环空闲才能执行该代码。我建议您尝试删除progress
调用并直接写入日志。我猜问题就会消失。 - Enigmativity