繁体   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