我试图了解如何有效地从文件中读取一些数据,做一些并行工作(每行)然后将新行写回文件系统。
我知道我可以做到这一点,一次一行..但我希望一次做几行 - 或者......如果一行是忙碌的'等待异步工作完成,然后转到下一行,等等。
这里有一些示例数据和逻辑...
Header
SomeId#1, SomeId#2, SomeId#3, Name, Has this line been processed and cleaned(true/false)
File Data
444,2,12,Leia Organa, true
121,33333,4,Han Solo, true
1,2,3,Jane Doe, false
1,4,11,John Doe, false
所以前两行已被处理,我将跳过这些行。 需要处理第3行和第4行。检查数据后,我希望将其保存回文件,如
1,33333,3,Jane Doe, true
所以这是一般逻辑......
DoWorkAsync()
< - 可能需要一秒或5 我只是希望我不必等待DoWorkAsync()
完成才能保存然后阅读下一行。我希望我可以开始阅读下一行......如果前一行完成..罚款..然后将该行保存到文件中的相同行号..然后再次移动到下一行。
就像我可以在同一时间工作5或10行一样......等待结果从第三方api回来......并行工作或其他什么。
这可以在.NET中完成吗?我确信.NET具有这方面的功能......我无法看到这样做的模式。
注意:我通常执行异步/等待I / O密集型操作(如命中文件系统或调用某些第三方api端点)和我用于CPU密集工作的Parallel.ForEach。
注意:为什么行尾的true/false
?因为我无法一次处理所有线路。我有api限制。
其他想法是有两个文件,一个用于PENDING,另一个用于PROCESSED。
答案 0 :(得分:1)
这是一个并行处理器的存根,它在批量处理行时使用async
/ await
。
此方法可确保在编写时保留相同的顺序。
public async Task ProcessFile()
{
const int parallelism = 5;
using (var readStream = File.OpenRead(@"c:\myinputfile"))
{
// put HERE your logic for skipping to a specific line
// e.g. readStream.Seek(lastPosition);
using (var reader = new StreamReader(readStream))
{
while (!reader.EndOfStream)
{
var tasks = new List<Task<string>>();
for (var i = 0; i < parallelism; i++)
{
var line = await reader.ReadLineAsync();
tasks.Add(DoWorkAsync(line));
if (reader.EndOfStream)
break;
}
var results = await Task.WhenAll(tasks);
using (var writeStream = File.Open(@"d:\myresultfile", FileMode.Append))
using (var writer = new StreamWriter(writeStream))
{
foreach (var line in results)
await writer.WriteLineAsync(line);
}
}
}
}
}
public async Task<string> DoWorkAsync(string line)
{
await Task.Delay(new Random().Next(1000, 5000));
// do some work and return line with last parameter = true
return line.Replace("false", "true"); // e.g.
}
它肯定需要改进,但它应该为你自己写一个很好的基础。