[英]file writing using blockingcollection
我有一個tcp偵聽器,它可以偵聽和寫入服務器中的數據。 我使用BlockingCollection
來存儲數據。 在這里,我不知道文件何時結束。 因此,我的文件流始終處於打開狀態。
我的代碼的一部分是:
private static BlockingCollection<string> Buffer = new BlockingCollection<string>();
Process()
{
var consumer = Task.Factory.StartNew(() =>WriteData());
while()
{
string request = await reader.ReadLineAsync();
Buffer.Add(request);
}
}
WriteData()
{
FileStream fStream = new FileStream(filename,FileMode.Append,FileAccess.Write,FileShare.Write, 16392);
foreach(var val in Buffer.GetConsumingEnumerable(token))
{
fStream.Write(Encoding.UTF8.GetBytes(val), 0, val.Length);
fStream.Flush();
}
}
問題是我無法在循環中放置文件流,否則我必須為每一行創建文件流,循環可能永遠不會結束。
如果您使用了DataFlow ActionBlock,則在.NET 4.5中這將容易得多。 一個ActionBlock接受並緩沖傳入的消息,並使用一個或多個任務異步處理它們。
您可以這樣寫:
public static async Task ProcessFile(string sourceFileName,string targetFileName)
{
//Pass the target stream as part of the message to avoid globals
var block = new ActionBlock<Tuple<string, FileStream>>(async tuple =>
{
var line = tuple.Item1;
var stream = tuple.Item2;
await stream.WriteAsync(Encoding.UTF8.GetBytes(line), 0, line.Length);
});
//Post lines to block
using (var targetStream = new FileStream(targetFileName, FileMode.Append,
FileAccess.Write, FileShare.Write, 16392))
{
using (var sourceStream = File.OpenRead(sourceFileName))
{
await PostLines(sourceStream, targetStream, block);
}
//Tell the block we are done
block.Complete();
//And wait fo it to finish
await block.Completion;
}
}
private static async Task PostLines(FileStream sourceStream, FileStream targetStream,
ActionBlock<Tuple<string, FileStream>> block)
{
using (var reader = new StreamReader(sourceStream))
{
while (true)
{
var line = await reader.ReadLineAsync();
if (line == null)
break;
var tuple = Tuple.Create(line, targetStream);
block.Post(tuple);
}
}
}
大多數代碼都涉及讀取每一行並將其發布到塊中。 默認情況下,ActionBlock一次僅使用一個任務來處理一條消息,在這種情況下很好。 如果需要並行處理數據,則可以使用更多任務。
讀取所有行后,我們通過調用Complete
通知該塊,並等待它通過await block.Completion
完成處理。
區塊的Completion
任務完成后,我們可以關閉目標流。
DataFlow庫的優點在於,您可以將多個塊鏈接在一起,以創建處理步驟的管道。 ActionBlock通常是此類鏈中的最后一步。 該庫會小心地將數據從一個塊傳遞到下一個塊,並沿鏈向下傳播完成。
例如,一個步驟可以從日志中讀取文件,第二個步驟可以使用正則表達式解析它們以找到特定的模式(例如錯誤消息)並將其傳遞,第三個步驟可以接收錯誤消息並將它們寫入另一個文件。 每個步驟將在不同的線程上執行,並且在每個步驟中緩沖中間消息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.