[英]How to handle Exceptions in a TPL Dataflow - Producer/Consumer
我有以下測試應用程序可以模擬我的應用程序場景:
class Program
{
static void Main()
{
Console.WriteLine("***Press R = record to new file, S = Stop Recording, E = Exit");
var timer = new Timer(Callback, null, 0, 1000);
while(!_Close) HandleInput(Console.ReadLine());
Console.WriteLine("Finished");
}
private static bool _Close;
private static void HandleInput(string input)
{
switch (input.ToLower())
{
case "r": CreateWriter();
break;
case "s": Console.WriteLine("File Closed: {0}", _FileWriter.Name);
_FileWriter.Dispose();
_FileWriter = null;
break;
case "e":
_Close = true;
break;
}
}
private static void CreateWriter()
{
if (_FileWriter != null)
_FileWriter.Dispose();
string filename = Path.Combine("C:\\", string.Format("{0:yyyy_MM_dd HH_mm_ss}.txt",DateTime.Now));
_FileWriter = new AsyncFileWriter(filename);
Console.WriteLine("New File Created: {0}", filename);
}
private static void Callback(object state)
{
if (_FileWriter != null)
_FileWriter.Produce(MakeData());
}
private static byte[] MakeData()
{
string data = string.Empty;
for (int i = 0; i < 50; i++)
{
data += string.Format("{0:yyyy-MM-dd HH:mm:ss.fff}{1}", DateTime.Now, Environment.NewLine);
}
return Encoding.UTF8.GetBytes(data);
}
private static AsyncFileWriter _FileWriter;
}
它使用以下類作為Consumer(/ producer):
public class AsyncFileWriter : IDisposable
{
private readonly FileStream _Filewriter;
private readonly Task _WriteTask;
private readonly BufferBlock<byte[]> _BufferBlock;
public AsyncFileWriter(string filename)
{
_Filewriter = new FileStream(filename, FileMode.CreateNew, FileAccess.Write, FileShare.None);
_BufferBlock = new BufferBlock<byte[]>();
_WriteTask = WriteToFile();
}
public void Produce(byte[] data)
{
_BufferBlock.Post(data);
}
public long Filesize { get; private set; }
public string Name { get { return _Filewriter.Name; } }
private async Task WriteToFile()
{
while (await _BufferBlock.OutputAvailableAsync())
{
byte[] data = _BufferBlock.Receive();
await _Filewriter.WriteAsync(data, 0, data.Length);
Filesize = _Filewriter.Length;
}
}
private async Task Complete()
{
_BufferBlock.Complete();
await Task.WhenAll(_WriteTask, _BufferBlock.Completion);
//now close the file
_Filewriter.Dispose();
}
public void Dispose()
{
Complete();
}
}
要注意的重要事項是:
我有幾個問題,因為我是TPL數據流庫的新手。
Produce()
,並且這里不會發生異常...這種模式是否有最佳實踐? Dispose有點壞,因為它不等到所有活動都關閉后再進行操作。 這可能不是您想要的。 看到http://blog.stephencleary.com/2013/03/async-oop-6-disposal.html 。
AsyncFileWriter具有無限制的緩沖區。 如果文件編寫器過載,將消耗越來越多的內存。
否則,AsyncFileWriter似乎可以。
但是由於文件系統具有自己的緩沖功能,因此您可能根本不用任何像AsyncFileWriter這樣的東西就可以擺脫困境。 僅寫入文件可能就足夠了。
關於例外:您可以為此公開一個事件。 或者,如果發生異常,則關閉編寫,記住該異常,並使類的使用者可以檢查該異常。 此外,生產必須開始失敗。 處置不應失敗,但是在處置該類的用戶之前,需要關閉它並檢查異常。
因此,要么使用事件,要么將類移到錯誤狀態。
對於消費者來說,錯誤狀態可能更好一些,因為異常是在閑暇時發現的,而不是通過事件推送的。 Complete
應該公開。 調用方應等待它,並在此處引發異常。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.