所以我正在编写一个方法,该方法应该处理大量字符串并为处理的每个字符串更新 UI。为此,我使用 async-await
模式,使用 Progress 报告器向主线程报告一个字符串,该字符串应该被更新。
问题是:它不起作用。即使我使用了 await 关键字,UI 也会被阻塞,就好像该方法正在同步运行一样。
这是我的代码的样子:
private async Task ProcessFile(string filePath, IProgress<string> progress)
{
string[] LinesToProcess = File.ReadAllLines(filePath);
int LineCount = Buffer.Count();
await Task.Factory.StartNew(() =>
{
for (int i = 0; i < Buffer.Count(); i++)
{
//Do actual processing here
progress.Report(string.Format("Lines processed: {0} / {1}", i, LineCount));
}
});
}
这是调用 ProcessFile
任务的方法
private async Task RunTask()
{
string filePath = //Get filePath somehow
await ProcessFile(filePath, new Progress<string>(line =>
{
ProcessedLabel.Text = line;
}));
}
最后,这是与 RunTask() 任务相关的按钮回调:
private async void Button_Click(object sender, EventArgs e)
{
await RunTask();
}
我简化了代码以提高可读性。任何帮助是极大的赞赏。谢谢!
最佳答案
我可以看到两个选项:
- 您处理许多行的速度如此之快,以至于 UI 线程一直忙于更新,没有时间实际显示结果。要解决此问题,请不要报告每一行的进度,而是仅每 100、1000 或任何适合您的行数报告一次。作为替代方案,您可以根据时间(例如每秒)报告进度。但这需要更复杂的代码。
- 您遇到了
Task.Factory.StartNew()
的问题,它在 UI 线程上运行,因为那是Current
TaskScheduler
。尽管我在您的代码中没有看到任何迹象表明是这种情况,所以我认为这不太可能。但是为了安全起见,您应该改用Task.Run()
。有关详细信息,请阅读 StartNew is Dangerous from Stephen Cleary .
关于c# - 如何防止我的异步方法阻塞 UI?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37759763/