Kry*_*oxx 3 c# asynchronous stream streamwriter task-parallel-library
我最近将我的LogManager类从一个转换static为singleton类,以便在WPF中更容易绑定(虽然我认为此问题在此之前也存在).检查每一件事是否一切正常后,我注意到一些奇怪的事 在SaveLoop我用我写日志文件,并将它们发送到视图的任务,因为我觉得它确实不太正常工作.
在视图中,它们几乎立即被添加,如果我关闭应用程序,SaveLoop任务将被取消,我可以在创建的文件中查看日志.但是,当应用程序崩溃时(或者我在Visual Studio中按停止按钮),带有日志的文件比视图中的实际日志数少约8-10个日志.
我注意到当写入不再BufferBlock包含日志时,编写器停止写入(在消息中间),并且只有在添加新日志时才会继续写入.
是因为BufferBlock停止任务中的每个异步操作,因为它没有更多的项目要提供?
这是我运行应用程序时控制台中的输出(LogStatus消息是另一个检测到过去1000毫秒内发生了任何变化的循环任务):
12345678
12345678
12345678
1Setting LogStatus=Idle
Run Code Online (Sandbox Code Playgroud)
我真的不知道如何处理这个问题,如果有人可以帮助我,将不胜感激!
SaveLoop任务(控制台输出仅用于调试目的):
private async Task SaveLoop(CancellationToken cancel)
{
string logPath = "logs\\";
string logFile = _startTime.ToString("yyyy-MM-dd_HH-mm-ss") + ".log";
string fullPath = Path.Combine(logPath, logFile);
if (!Directory.Exists(logPath))
Directory.CreateDirectory(logPath);
using (FileStream fileStream = new FileStream(fullPath, FileMode.Append, FileAccess.Write, FileShare.Read, 8192, useAsync: true))
{
using (StreamWriter writer = new StreamWriter(fileStream))
{
while (true)
{
LogMessage logMessage = null;
try
{
Console.Write("1");
logMessage = await _logQueue.ReceiveAsync(cancel).ConfigureAwait(false);
Console.Write("2");
await writer.WriteAsync(String.Format("({0}) ", logMessage.LogID)).ConfigureAwait(false);
Console.Write("3");
await writer.WriteAsync(String.Format("[{0}][{1}] ", logMessage.Time.ToString("HH:mm:ss:fff"), logMessage.Level.ToString())).ConfigureAwait(false);
Console.Write("4");
await writer.WriteAsync(logMessage.Message).ConfigureAwait(false);
Console.Write("5");
await writer.WriteLineAsync(String.Format(" ({0} - {1})", logMessage.Method, logMessage.Location)).ConfigureAwait(false);
Console.Write("6");
AddLogToCollections(logMessage);
Console.Write("7");
_timeout = 10;
if (cancel.IsCancellationRequested)
{
Console.WriteLine("0");
break;
}
Console.WriteLine("8");
}
catch (TaskCanceledException tce)
{
Console.WriteLine("Task canceled!");
Console.WriteLine("{0} {1}", tce.Message, tce.Source);
break;
}
catch (Exception e)
{
Console.WriteLine("{0} {1}", e.Message, e.Source);
Console.WriteLine("{0}", e.StackTrace);
if (logMessage != null)
{
Console.WriteLine("Log: {0}", logMessage.ToString());
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这与Dataflow块无关.发生这种情况的原因是因为StreamWriter并且FileStream使用缓冲更有效.因此,您应该做的是await writer.FlushAsync()在循环结束时添加,这会清空缓冲区并将数据写入磁盘.