2017-02-25 171 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()方法中異步分派更新,並添加一個計數器以跟蹤其中有多少當前未完成,並在回調中等待該櫃檯超過了一些合理的門檻

現在,所有這一切都表明......您似乎很可能遇到了這個問題,因爲您正在從某個數據源讀取數據,這比數據庫本身快得多。如果是這樣的話,這是值得懷疑的,爲什麼這些應該完全異步完成。也許有些東西你沒有分享,這證明了異步方法的合理性,但是根據你迄今發佈的內容,似乎整個讀取和更新數據庫邏輯應該只在一個線程/工作人員/任務/隨你。