簡體   English   中英

管道圖案和一次性物品

[英]Pipeline pattern and disposable objects

最近,我開始研究Pipeline模式,也稱為Pipes and Filters 我認為這是構造代碼和處理數據的應用程序的好方法。 我將本文用作管道和步驟實現的基礎(但這並不是那么重要)。 像往常一樣,博客只涉及簡單的場景,但就我而言,我需要(或可能不需要)處理可能在過程中傳播的IDisposable對象。

例如流

讓我們考慮一個簡單的管道,該管道應加載csv文件並將其行插入某些db中。 簡單地講,我們可以實現這樣的功能

Stream Step1(string filePath)
IEnumerable<RowType> Step2(Stream stream)
bool Step3(IEnumerable<RowType> data)

現在我的問題是,這是否是一個好方法。 因為如果我們在逐步處理中實現該目標,則Stream對象將離開第一步,並且很容易陷入內存泄漏問題。 我知道有人可能會說我應該擁有要加載和反序列化數據的Step1 ,但是我們正在考慮簡單的過程。 我們可能會有更復雜的方法,在這些方法中通過Stream更為合理。

我想知道如何實現這樣的管道以避免內存泄漏,也避免將整個文件加載到MemoryStream (這樣會更安全)。 如果出現問題,是否應該以某種方式將每個步驟包裝在try..catch塊中以調用Dispose() 或者我應該通過所有IDisposable資源投入到Pipeline對象,將被包裝using處置正確處理過程中產生的所有的資源?

如果計划像Step3( Step2( Step1(filePath) ) ) ,則Step2應該處理流。 它可以使用c#的yield return功能,該功能在下面創建IEnumerator <>的實現,該實現實現IDisposable ,並允許“訂閱”完成枚舉的“事件”並調用Stream.Dispose 例如:

IEnumerable<RowType> Step2(Stream stream)
{
    using(stream)
    using(StreamReader sr = new StreamReader(stream))
    {
        while(!sr.EndOfStream)
        {
           yield return Parse(sr.ReadLine()); //yield return implements IEnumerator<>
        }
    } // finally part of the using will be called from IEnumerator<>.Dispose()        
}

然后,如果Step3使用LINQ

bool Step3(IEnumerable<RowType> data) => data.Any(item => SomeDecisionLogic(item));

foreach

bool Step3(IEnumerable<RowType> data)
{
    foreach(var item in data)
        if(SomeDecisionLogic(item)))
            return true;
}

為了枚舉,它們兩個都保證調用IEnumerator<>.Dispose()ref1ECMA-334 C#Spec,ch.13.9.5 ),這將調用Stream.Dispose

如果至少在兩個不同的系統之間進行交互並且可以並行執行工作,則IMO值得擁有一條管道。 否則會增加開銷。

在這種情況下,有2個系統:CSV文件所在的文件系統和數據庫。 我認為管道應該至少有兩個並行運行的步驟:

IEnumerable<Row> ReadFromCsv(string csvFilePath)
void UpdateDabase<IEnumerable<Row> rows)

在這種情況下,應該很清楚Stream綁定到ReadFromCsv

IEnumerable<Row> ReadFromCsv(path)
{
  using(var stream = File.OpenRead(path))
  {
      var lines = GetLines(stream); // yield one at a time, not all at once
      foreach (var line in line) yield return GetRow(line);
  }
}

我認為范圍取決於步驟-而步驟又取決於您根據需要設計管道的方式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM