我们知道C#的散装/分批流库吗
我正在一个对性能要求苛刻的项目中工作,因此为了提高效率,我们需要批量(批处理)几个操作(例如,将数据持久存储到数据库中)。
但是,我希望我们的代码保持易于理解的流程,例如:
input = Read(); parsed = Parse(input); if (parsed.Count > 10) { status = Persist(parsed); ReportSuccess(status); return; } ReportFailure();
我在这里寻找的功能是自动使Persist()批量发生(并异步异步运行),但对用户的行为就好像是同步的一样(用户应阻止直到批量操作完成)。我希望实现者能够实现Persist(ICollection)。
我研究了基于流的编程,对此我并不十分熟悉。我在Chere看到了一个用于fbp的库,并与Microsoft的Workflow Foundation进行了一些接触,但是我的印象是,这两个库对于我所需要的都是过大的。我们将使用什么来实现批量流动行为?
请注意,我希望获得与我编写的代码完全相同的代码(易于理解和调试),因此涉及产量或者配置以便将流彼此连接的解决方案对于我的目的来说是不够的。另外,链接
不是我想要的,我不想先构建一个链然后运行它,我想要看起来像是简单流程的代码("做A,做B,如果C然后做D") 。
解决方案
回答
我不知道这是否是我们需要的,因为它基于sqlserver,但是我们是否尝试过看看SSIS和DTS?
回答
常见问题不是调用Persist,而是通常将命令(或者沿这些行的smt)加载到Persistor类中,然后在循环完成后,我调用Persistor.Persist来保留批处理。
仅几个指针如果生成sql,则添加到持久性中的命令可以某种方式表示查询(使用内置对象,自定义对象或者仅查询字符串)。如果我们正在调用存储过程,则可以使用命令将内容添加到xml片段中,当我们调用persist方法时,这些内容将向下传递到SP。
希望对我们有帮助。很确定有一个模式,但是不知道这个名字:)
回答
我们可以做的一件简单的事情是创建一个MemoryBuffer,在其中推送消息,这些消息只是将它们添加到列表中并返回。此MemoryBuffer有一个System.Timers.Timer,它会定期调用并进行"实际"更新。
可以在http://www.fantail.net.nz/wordpress/?p=5的Syslog服务器(C#)中找到一种这样的实现,其中syslog消息会定期成批记录到SQL Server。
如果将信息推送到数据库很重要,则此方法可能不好,因为如果出现问题,我们将丢失MemoryBuffer中的消息。
回答
如何使用BackgroundWorker
类将每个项目异步保留在单独的线程上?例如:
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Threading; class PersistenceManager { public void Persist(ICollection persistable) { // initialize a list of background workers var backgroundWorkers = new List<BackgroundWorker>(); // launch each persistable item in a background worker on a separate thread foreach (var persistableItem in persistable) { var worker = new BackgroundWorker(); worker.DoWork += new DoWorkEventHandler(worker_DoWork); backgroundWorkers.Add(worker); worker.RunWorkerAsync(persistableItem); } // wait for all the workers to finish while (true) { // sleep a little bit to give the workers a chance to finish Thread.Sleep(100); // continue looping until all workers are done processing if (backgroundWorkers.Exists(w => w.IsBusy)) continue; break; } // dispose all the workers foreach (var w in backgroundWorkers) w.Dispose(); } void worker_DoWork(object sender, DoWorkEventArgs e) { var persistableItem = e.Argument; // TODO: add logic here to save the persistableItem to the database } }