快速将数据保存在磁盘上;如何?使用辅助内存缓冲区?

时间:2018-09-20 11:51:34

标签: c# memory buffer

我用c#编写了一个应用程序,以从以太网络上连接的某些设备读取一些数据(以轮询模式)。启动了许多并行任务,每个任务针对配置的每个设备。在所有任务结束时,读取的数据都存储在stringbuilder中,然后以追加模式保存到文件中。如果将轮询时间设置得很高(例如,大于5/6秒),则一切正常。对于较短的时间,磁盘IO活动可能无法保存strinbuilder中包含的数据量(当需要启动第二个保存数据的过程时,第一个保存过程尚未结束,等等)。我怎么解决这个问题?我想创建一个类似于“内存缓冲区”的控件,该控件将用设备数据填充的stringbuilder(sbData)复制到用于在固定时间(例如,每30秒)保存数据的支持stringbuilder(sbAux)。成功保存数据后,请在30秒结束时再次复制新数据(sbAux = sbData)。还有其他方法吗?你能给我建议吗?

非常感谢大家的建议。

1 个答案:

答案 0 :(得分:0)

好的-如果读取数据的时间可能在50到x,000毫秒之间,那么您将不得不忘记将所有数据保持在整洁的行中。相反,我建议两个阶段。

您的第一阶段是真正快速的缓冲区,它只是尽可能快地接受数据。它仅执行最小限度的检查-例如,确保数据格式正确。您必须确定“最小检查”的含义,但是它只会抛出明显错误的数据(可能只是忽略它并记录警告)。其他任何内容都只会添加到队列中。队列的目的是将数据添加到队列的后面并从前面读取。您必须决定最多可以容纳多少数据,只有实验才能告诉您。

您可以在以下位置找到有关如何使用队列的信息:

您将不得不从Queue继承以适合您自己的数据并使它成为线程安全的,因为将有多个线程正在对其进行写入和读取。

您的工作线程从设备读取数据并在可用时提交读数。他们不会尝试对数据进行排序,也不必担心只是丢失数据:

  • 读取数据
  • 将它扔到队列中
  • 忘记数据
  • 睡觉或继续阅读下一个需要阅读的东西

请记住:将数据从设备传递到队列是时间紧迫的,因此在此操作的这一部分中无需“思考”。

我会考虑批量处理您的数据-即您添加单个项目,然后将其添加到一个块中,例如32个读数。整个块被添加到队列中。读取数据时,它不会读取一次,而是读取一批x项(在本例中为32)。这意味着队列处理的写操作多于读操作。

您的第二阶段是所有大脑所在的地方。该缓冲区(或多个缓冲区,具体取决于要写入的文件数)从队列中读取并排序。您必须决定如何订购它的规则。但是此操作不是时间紧迫的。它从队列中读取,查看数据用于什么设备,时间戳是什么,并确定是否由于超时而丢失任何读数,并构造要保存到磁盘的数据。如果您要为每个设备创建1个文件,那么这就是数据分离的地方。

将这两个操作分开的要点是,排序和将其写入磁盘这一相对较慢的部分不会占用您工作中时间紧迫的部分。不要只是继续在模型中添加线程-进行相反的操作,并尽可能减少开销。第二阶段的循环应该比第一阶段慢得多。

这是一个大概的工作原理:

Rough drawing of the 2 stages

正如Doc在“回到未来”中所说,“您必须原谅该模型的残酷性。” 我知道这只是一般指导,但我希望它能对您有所帮助,并朝正确的方向推。

祝你好运和亲切的问候!

亚当。