我有一个类Reader
创建Task
并批量读取数据。每次完成阅读批处理时,它都会通过参数中传递的IProgress
报告进度。然后我将批处理保存到NoSQL数据库。问题是它有时可以比将批处理保存到数据库更快地报告进度。
我认为如果保存还没有结束,那么一个好的解决方案就是阻止Task
。我真的不知道如何实现它。我需要能够通知读取已完成的内容,然后等待保存到db的通知已完成并且可以继续读取。
伪码:
阅读器:
public async Task<bool> ReadAsync(IProgress<Tuple<DataTable, int>> statusCallback) {
return await Task.Run(() =>
{
while(lineCount <= BufferSize) {
// Read data
}
statusCallback.Report(new Tuple<DataTable, int>(data, progress);
}
}
主要
public Main() {
var progress = new Progress<Tuple<DataTable, int>>(ReaderStatusCallback);
reader.ReadAsync(progress);
}
private void ReaderStatusCallback(Tuple<DataTable, int> tuple)
{
var data = tuple.Item1.ToDocumentData();
var progress = tuple.Item2;
_progressBar.Increment(progress);
_docData.Data = data;
_repository.Add(_docData);
}
答案 0 :(得分:0)
这里最简单的解决方案是不使用异步调度更新的IProgress<T>
实现。例如:
class BasicProgress<T> : IProgress<T>
{
private readonly Action<T> _handler;
public BasicProgress(Action<T> handler)
{
_handler = handler;
}
private void IProgress<T>.Report(T value)
{
_handler(value);
}
}
然后,对statusCallback.Report()
的调用不会返回,直到数据库更新为止。
如果没有更多的背景,就不可能确定什么是最好的。但是,您可能会发现允许数据库更新至少在某种程度上排队的一些价值。在这种情况下,您可以通过仍使用同步IProgress<T>
实现修改上述想法,但在ReaderStatusCallback()
方法中异步调度更新,并添加计数器以跟踪当前有多少如果该计数器超过某个合理的阈值,则在回调中等待。
现在,所有这一切......似乎你遇到了这个问题,因为你正在阅读一些比数据库本身快得多的源代码。如果是这样,那么为什么任何这些都应该异步完成是值得怀疑的。也许你没有共享的东西可以证明异步方法是合理的,但是根据你到目前为止发布的内容,似乎整个读取和更新数据库逻辑应该只是在一个线程/工人/任务/无论如何。