[英]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.