C# 有花纹的。通过这些问题,我只是在寻找一般实施问题的答案。至于“索引”,它实际上是一个可能的解决方案,以确保我知道我正在为哪个文件维护状态(这样我实际上不需要同步文件处理)。我一直在寻找更好的东西,但我想我会接受的。这非常适合我。虽然我只有一个问题。有没有一
C# 有花纹的。通过这些问题,我只是在寻找一般实施问题的答案。至于“索引”,它实际上是一个可能的解决方案,以确保我知道我正在为哪个文件维护状态(这样我实际上不需要同步文件处理)。我一直在寻找更好的东西,但我想我会接受的。这非常适合我。虽然我只有一个问题。有没有一,c#,tpl-dataflow,C#,Tpl Dataflow,有花纹的。通过这些问题,我只是在寻找一般实施问题的答案。至于“索引”,它实际上是一个可能的解决方案,以确保我知道我正在为哪个文件维护状态(这样我实际上不需要同步文件处理)。我一直在寻找更好的东西,但我想我会接受的。这非常适合我。虽然我只有一个问题。有没有一种方法可以限制解析行的数量,这样就不会耗尽内存。我认为这样做的一种方法可能是在解析器和处理器之间引入批处理块和缓冲块,这样我就可以使用SendAsync手动产生反压力。这是对的吗?@LostRaider1297 AFAIK要控制内存使用,只需将
有花纹的。通过这些问题,我只是在寻找一般实施问题的答案。至于“索引”,它实际上是一个可能的解决方案,以确保我知道我正在为哪个文件维护状态(这样我实际上不需要同步文件处理)。我一直在寻找更好的东西,但我想我会接受的。这非常适合我。虽然我只有一个问题。有没有一种方法可以限制解析行的数量,这样就不会耗尽内存。我认为这样做的一种方法可能是在解析器和处理器之间引入批处理块和缓冲块,这样我就可以使用SendAsync手动产生反压力。这是对的吗?@LostRaider1297 AFAIK要控制内存使用,只需将管道中的所有块配置为
BoundedCapacity
。不需要其他技巧。这就产生了一个问题,即下游区块的故障可能会导致上游区块卡住。(对它们调用SendAsync
将永远不会完成)您可以寻找解决此问题的方法。@LostRaider1297顺便说一句,我对每个文件的专用处理器块的建议使得很难控制所有这些块组合的并行度。有一种解决方案,可以使用有限的并发性来配置它们TaskScheduler
。你可以找到这个想法的一个例子。@LostRaider1297另一个建议。您可以使用自己选择的硬编码TKey
创建自己的struct Keyed
类型,而不是使用ValueTuple
作为有效负载。这样声明块就不那么麻烦了,因为您只需声明值的类型,而不必声明键。例如:var parser=newtransformblock(…
static public IPropagatorBlock<string, string[]> CreatePipeline(int batchSize)
{
var fileReadingBlock = new TransformManyBlock<string, string>((filePath) =>
{
return File.ReadLines(filePath);
}, new ExecutionDataflowBlockOptions { EnsureOrdered = true, MaxDegreeOfParallelism = Environment.ProcessorCount});
var fileParsingBlock = new TransformBlock<string, string[]>((line) =>
{
return line.Split(",");
}, new ExecutionDataflowBlockOptions { EnsureOrdered = true, MaxDegreeOfParallelism = Environment.ProcessorCount});
return DataflowBlock.Encapsulate(fileReadingBlock, fileParsingBlock);
}
var parser = new TransformBlock<(int Id, string Line), (int Id, string[])>(line =>
{
return (line.Id, line.Line?.Split(","));
});
var reader = new TransformManyBlock<(int Id, string Path), (int, string)>(file =>
{
var processor = CreateProcessor(file.Id);
// Create a conditional link from the parser block to the processor block
var link = parser.LinkTo(processor, entry => entry.Id == file.Id);
return File
.ReadLines(file.Path)
.Select(line => (file.Id, line))
.Append((file.Id, null)); // Completion signal
});
ActionBlock<(int Id, string[] LineParts)> CreateProcessor(int fileId)
{
var streamWriter = new StreamWriter($@"C:\{fileId}.out");
return new ActionBlock<(int Id, string[] LineParts)>(line =>
{
if (line.LineParts == null)
{
streamWriter.Close(); // Completion signal received
return;
}
streamWriter.WriteLine(String.Join("|", line.LineParts));
});
}
reader.LinkTo(parser);