2017-02-25 213 views
1

我有一个类Reader创建Task并批量读取数据。每次完成读取批次时,都会通过传入参数IProgress报告进度。然后我将这批保存到NoSQL数据库。问题是它有时可以比将批次保存到数据库更快地报告进度。块异步任务

我认为如果保存尚未完成,一个好的解决方案是阻止Task。我真的不知道如何实现它。我需要的东西会通知阅读已完成,然后等待通知保存到数据库已完成,并且可以继续阅读。

伪代码:

读者:

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

您的保存任务是否异步呢? – Sparrow

+0

不,我将它保存在UI线程上 – FCin

+0

如果您发布了一些伪代码,想出想法会更容易。我假设读者类正在使用循环。也许你可以有一个单独的类来保存,并有一个标志来显示它是否繁忙,并且在你的阅读器循环中,在尝试读取新的批处理之前检查该标志。当保存完成后,您可以看中并使用事件通知读者类,或者只是使用循环,不断检查标志的值,直到准备就绪。等待(或阻止)异步方法,虽然 – Sparrow

回答

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()方法中异步分派更新,并添加一个计数器以跟踪其中有多少当前未完成,并在回调中等待该柜台超过了一些合理的门槛

现在,所有这一切都表明......您似乎很可能遇到了这个问题,因为您正在从某个数据源读取数据,这比数据库本身快得多。如果是这样的话,这是值得怀疑的,为什么这些应该完全异步完成。也许有些东西你没有分享,这证明了异步方法的合理性,但是根据你迄今发布的内容,似乎整个读取和更新数据库逻辑应该只在一个线程/工作人员/任务/随你。