考虑以下实现,一个方法接受一个IProgress<int>
,迭代超过 10000 个对象。数组变量返回 10000 个对象,numbers
但IProgress<int>
报告仅在 9970 - 9980 个对象之间。每次运行都会有所不同,因此有些人会“迷路”。
protected async override Task<int[]> CollectDataAsyncImpl(IProgress<int> progress) {
return await Task.Run<int[]>(() => {
var numbers = new List<int>();
foreach (var idx in new Int32Range(1, 10000).AsEnumerable().Index()) {
numbers.Add(idx.Value);
if (progress != null) {
progress.Report(idx.Value);
}
}
return numbers.ToArray();
});
}
作为参考,这是我运行的测试。它在第三个 assert 失败Assert.Equal(10000, result[9999]);
。
[Fact]
async void ReportsProgress() {
var sut = new IntegerCollector();
var result = new List<int>();
var output = await sut.CollectDataAsync(new Progress<int>(i => result.Add(i)));
Assert.Equal(10000, output.Length);
Assert.Equal(1, result[0]);
Assert.Equal(10000, result[9999]);
}
显然我做错了什么,或者我不了解任务/线程的内部结构。我的执行IProgress<int>
不new Progress<int>(i => result.Add(i))
正确吗?我应该让那个线程安全吗?如果是,我该怎么做?
如果需要,GitHub 有您可以克隆和测试的代码:https ://github.com/KodeFoxx/Kf.DataCollection/tree/master/Source/Kf.DataCollection