所以我尝试使用IProgress<T>
来使用任务进度通知。这是我的工作:
Progress<T>
并将处理程序附加到其ProgressChanged
事件。Task
个对象以执行工作单元。每个任务使用Progress
对象来报告进度(进而调用ProgressChanged
并更新UI)。Task.WaitAll()
阻止所有任务完成。最后显示完成消息。代码看起来像这样:
IProgress<Tuple<DataRow, MyVM>> BakeProgress;
BakeProgress = new Progress<Tuple<DataRow, MyVM>>();
((Progress<Tuple<DataRow, MyVM>>)BakeProgress).ProgressChanged += (sender, args) =>
{
_BakeProgress += 100.0 / AllDataRows.Length;
RaisePropertyChanged(NameOf(BakeProgress));
};
var BakeTasks = new List<Task>();
foreach (var dr in AllDataRows) {
BakeTasks.Add(Task.Run(() =>
{
var Baked = MyBakingFunc();
BakeProgress.Report(new Tuple<DataRow, MyVM>(dr, Baked));
return Baked;
}));
}
Task.WaitAll(BakeTasks.ToArray()); //Shouldn't this wait
MessageBox.Show("Baking Completed");
令我惊讶的是,此代码在点击MessageBox
事件处理程序之前点击ProgressChanged
行甚至一次。我做错了什么?
N.B。它会为每个Task实例执行一次ProgressChanged
事件处理程序,但只有在命中完成的行后才会执行。
N.B。啊,我确实读过this,但由于这是WPF,我们确实有一个同步上下文,其中创建了Progress
对象。