- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一项服务接受包含需要批量插入数据库的 CSV 数据的输入流,并且我的应用程序尽可能使用 async/await。
过程是:使用CsvHelper的CsvParser解析流,将每一行添加到DataTable,使用SqlBulkCopy将DataTable复制到数据库。
数据可以是任意大小,所以我想避免一次将整个数据读入内存 - 显然,无论如何我都会在最后将所有数据保存在 DataTable 中,因此内存中基本上有 2 个副本。
我想尽可能异步地完成所有这些操作,但 CsvHelper 没有任何异步方法,因此我想出了以下解决方法:
using (var inputStreamReader = new StreamReader(inputStream))
{
while (!inputStreamReader.EndOfStream)
{
// Read line from the input stream
string line = await inputStreamReader.ReadLineAsync();
using (var memoryStream = new MemoryStream())
using (var streamWriter = new StreamWriter(memoryStream))
using (var memoryStreamReader = new StreamReader(memoryStream))
using (var csvParser = new CsvParser(memoryStreamReader))
{
await streamWriter.WriteLineAsync(line);
await streamWriter.FlushAsync();
memoryStream.Position = 0;
// Loop through all the rows (should only be one as we only read a single line...)
while (true)
{
var row = csvParser.Read();
// No more rows to process
if (row == null)
{
break;
}
// Add row to DataTable
}
}
}
}
这个解决方案有什么问题吗?甚至有必要吗?我已经看到 CsvHelper 开发人员特别没有添加异步功能 ( https://github.com/JoshClose/CsvHelper/issues/202 ),但我并没有真正理解不这样做背后的原因。
编辑:我刚刚意识到这个解决方案不适用于列包含换行符的情况:(我猜我只需要将整个输入流复制到 MemoryStream 或其他东西
EDIT2:更多信息。
这是在一个库中的异步方法中,我试图在其中一直执行异步操作。它可能会被 MVC Controller 使用(如果我只是想从 UI 线程卸载它,我只需要 Task.Run() 它)。大多数情况下,该方法将等待外部源,例如数据库/DFS,我希望线程在它处于等待状态时被释放。
CsvParser.Read() 会阻塞,即使阻塞的是读取流(例如,如果我试图读取的数据驻留在世界另一端的服务器上),而如果 CsvHelper 将实现一个使用 TextReader.ReadAsync() 的异步方法,那么我就不会因为等待我的数据从迪拜到达而受阻。据我所知,我并不是在请求围绕同步方法的异步包装器。
EDIT3:从遥远的 future 更新!异步功能实际上早在 2017 年就已添加到 CsvHelper 中。我希望我工作的公司的某个人从那时起已经升级到更新的版本!
最佳答案
Eric lippert 使用 a metaphor of cooking a meal in a restaurant 解释了 async-await 的实用性.根据他的解释,如果您的线程无事可做,那么异步执行某些操作是没有用的。
此外,请注意,当您的线程正在做某事时,它不能做其他事情。只有当您的线程正在等待某事时,它才能做其他事情。您在流程中等待的事情之一是读取文件。当线程逐行读取文件时,它必须等待几次才能读取行。在此等待期间,它可以做其他事情,例如解析读取的 CSV 数据并将解析后的数据发送到您的目的地。
解析数据不是您的线程必须等待其他进程完成的过程,就像读取文件或将数据发送到数据库时必须做的那样。这就是为什么没有解析过程的异步版本。普通的异步等待不会帮助您的线程保持忙碌,因为在解析过程中没有什么可等待的,因此在解析过程中您的线程将没有时间做其他事情。
当然,您可以使用 Task.Run ( () => ParseReadData(...)) 将解析过程转换为可等待的任务,并等待此任务完成,但在 Eric Lippert 餐厅的类比中,这会为厨师解冻做这项工作,而你却坐在柜台后面无所事事。
但是,如果您的线程有一些有意义的事情要做,而读取的 CSV 数据正在被解析,例如响应用户输入,那么在单独的任务中开始解析可能会很有用。
如果你完整的读取-解析-更新数据库的过程不需要和用户交互,但是你需要你的线程在做这个过程的同时可以自由地做其他事情,那么可以考虑把完整的过程放在一个单独的任务中,并且开始任务而不等待它。在那种情况下,您只需要使用您的界面线程来启动其他任务,并且您的界面线程可以自由地做其他事情。与流程的总时间相比,开始这项新任务的成本相对较小。
再说一遍:如果你的线程没有别的事可做,就让这个线程去做处理,不要启动其他任务去做。
关于c# - CsvHelper - 异步读取流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37063170/
CSVHelper v23 中的重大更改包括“所有委托(delegate)现在都接受单个结构参数”。 PrepareHeaderForMatch 是这些委托(delegate)之一。我收到编译错误“委
我正在尝试使用 CsvHelper 来改进我从对象到 csv 记录/行的手动转换过程。我创建了一个复杂的 ClassMap我想用它来将对象列表写入文件。如何添加 ClassMap到 CsvHelper
我有一个使用 CSVHelper (v19.0.0) 的类库。我在 VS2019(版本 16.5.5;.NET 4.8.03752)中通过 Nuget 安装了 CSVHelper,并且可以确认该包位于
我有一个使用 CSVHelper (v19.0.0) 的类库。我在 VS2019(版本 16.5.5;.NET 4.8.03752)中通过 Nuget 安装了 CSVHelper,并且可以确认该包位于
我正在使用 CsvHelper 将小巧的对象转换为 CsvFile。我正在使用类映射来映射索引和名称映射的属性。问题是在按如下所述写入记录之前,我需要带有表标题的行: 没有标题的旧代码: usin
您好,我正在尝试使用 CsvHelper,并最终将我的数据写入 .csv 文件,但如果尝试读取数据,结果总是空的。它读取 header ,然后 csv.Read() 似乎跳过了所有数据。 Sperrn
在 CsvHelper 的早期版本中,我可以像这样设置默认分隔符: using var csv = new CsvReader(reader, CultureInfo.CurrentCulture);
我正在使用 CsvHelper 我需要用引号包裹所有值。 那可能吗? 数据 = 是一个列表 using (StreamWriter textWriter = new StreamWriter(pat
我正在尝试读取上传的 CSV 文件,在对数据执行任何操作之前,我需要检查第一个 header 名称以确保它是正确的文件。我一直在试图找到一种方法来做到这一点,但读者却跳到第二行。有没有直接选择其中一个
我的文件中有以下格式的数据。 HEADER|ReportItem Name: Margin Ri..... Account Id/Margin Id|Account Name|Ba...... //
我正在使用出色的 CsvHelper 库(当前为 v12.2.2)来生成 CSV 文件,并且我正在尝试添加我自己的自定义属性以直接在类中指定特殊格式。 我正在写的记录看起来像这样(尽管集成需要大约 2
我在变量中有一个字符串,而不是在文件中。 我可以使用 CSVHelper ( https://joshclose.github.io/CsvHelper/ ) 来解析字符串并将其映射到我的对象上吗?
我正在成功使用类CsvReader并对此感到满意,但是,我使用的文件是由一个小组生成的,该小组在不通知我的情况下更改了列格式。 因此,一会儿一切正常,然后第二天早上事情中断,csv.GetRecord
我正在尝试读取逗号分隔的 csv 文件,除非字段包含逗号,否则该文件在大多数情况下都不是文本限定的。一个例子是可以包含逗号的地址行。当发生这种情况时,列将在我的映射对象内分流。 AddressLine
我对 .NET 的 CsvMapper 有疑问。我正在使用类映射器将对象映射到这样的 csv 文件中: Map(x => x.ProductId).Name("ProductId"); 这工作正常,但
我对 .NET 的 CsvMapper 有疑问。我正在使用类映射器将对象映射到这样的 csv 文件中: Map(x => x.ProductId).Name("ProductId"); 这工作正常,但
我正在尝试将 CsvWriter 配置为使用特殊字符串“#NULL#”作为可为 null 的字符串属性。对于读者来说,它可以通过设置 csvReader.Configuration.TypeConve
我有一项服务接受包含需要批量插入数据库的 CSV 数据的输入流,并且我的应用程序尽可能使用 async/await。 过程是:使用CsvHelper的CsvParser解析流,将每一行添加到DataT
我有以下 CSV。 Org Defined ID,Username,FirstName,LastName,Attempt #,Attempt Start,Attempt End,Section #,Q
我有一个不可变类,我想写入和读取 CSV 文件。问题是我在读取 CSV 时遇到异常,尽管已经映射了对象并设置了一个应该允许它工作的配置。 为此,我使用 CsvHelper .不可变类如下所示。 pub
我是一名优秀的程序员,十分优秀!