【发布时间】:2018-02-24 03:38:58
【问题描述】:
这是我尝试过的 - 就刷新 UI 而言,它可以工作,但我认为这不是 async / await 的最佳用途。我该如何改进?
private async void btnQuickTest_Click(object sender, RoutedEventArgs e)
{
XmlReader reader;
int rowCount = 0;
using (reader = XmlReader.Create("someXmlFile.xml"))
{
while (reader.Read())
{
rowCount++;
DoSomeProcessingOnTheUIThread(reader);
//only update UI every 100 loops
if (rowCount > 0 && rowCount % 100 == 0)
{
//yay! release the UI thread
await Task.Run(() =>
{
Application.Current.Dispatcher.Invoke(
() =>
{
txtRowCount.Text = string.Format("{0}", rowCount);
});
});
}
} //end-while
}//end-using
}
有什么更好的方法?
更新: 我根据 Clemens 的回答避免了 Dispatcher.Invoke,方法是将处理发送到后台任务,并直接在 UI 上更新进度。 我的代码现在看起来像。
private async void btnQuickTest_Click(object sender, RoutedEventArgs e)
{
XmlReader reader;
int rowCount = 0;
using (reader = XmlReader.Create("someXmlFile.xml"))
{
while (reader.Read())
{
rowCount++;
await DoSomeProcessing(reader);
//only update UI every 100 loops
if (rowCount % 100 == 0)
{
txtRowCount.Text = string.Format("{0}", rowCount);
}
} //end-while
}//end-using
MessageBox.Show("I am done!");
}
private Task DoSomeProcessing(XmlReader reader)
{
Task t =Task.Run(() =>
{
//Do my processing here.
});
return t;
}
更新#2: 反思一下,为什么我要在每个循环上创建一个新任务? 在一个后台任务中运行整个循环可能会更好。并定期发起回调以显示进度;请参阅下面的其他答案。
【问题讨论】:
-
如果您的代码有效,但您希望有人提出改进建议,您可能想在 Code Review 上提出这个问题。
-
您是否应该在非 UI 线程上进行“一些处理”?
-
DoSomeProcessingOnTheUIThread 是做什么的?
-
DoSomeProcessingOnTheUIThread() 只是我必须对 XML 文件进行的一些处理;即我要处理的“肉”,我很懒惰,并试图避免回调 UI 线程以通知进度。
-
您更新的代码看起来不错。附言。次要的,习惯上用“Async”来结束异步运行的方法的名称;等待 DoSomeProcessingAsync()。
标签: wpf async-await task-parallel-library