【问题标题】:Async StreamWriter Loop stops writing when BufferBlock is empty当 BufferBlock 为空时,异步 StreamWriter 循环停止写入
【发布时间】:2013-06-13 05:49:37
【问题描述】:

我最近将 LogManager 类从 static 转换为 singleton 类,以便在 WPF 中进行绑定(尽管我认为在此之前也存在此问题)。检查一切是否一切正常后,我发现了一些奇怪的东西。我用于将日志写入文件并将它们发送到视图的SaveLoop 任务并没有像我想象的那样工作。

在视图中它们几乎都是立即添加的,如果我关闭应用程序,SaveLoop 任务将被取消,我可以查看创建文件中的日志。但是,当应用程序崩溃(或者我在 Visual Studio 中按下停止按钮)时,带有日志的文件包含的日志比视图中的实际日志数少大约 8-10 个。

我注意到,当BufferBlock 不再包含日志时,作者停止写入(在消息中间),只有在添加新日志时才会继续。

是不是因为BufferBlock 停止了任务中的每个异步操作,因为它没有更多的项目要提供?

这是我运行应用程序时控制台中的输出(LogStatus 消息是另一个循环任务,用于检测在过去 1000 毫秒内是否有任何变化):

12345678
12345678
12345678
1Setting LogStatus=Idle

我真的不知道如何处理这个问题,如果有人可以帮助我,将不胜感激!


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());
                    }
                }
            }
        }
    }
}

【问题讨论】:

    标签: c# asynchronous stream task-parallel-library streamwriter


    【解决方案1】:

    这与 Dataflow 块无关。发生这种情况的原因是StreamWriterFileStream 使用缓冲来提高效率。因此,您应该做的是在循环末尾添加await writer.FlushAsync(),这会清空缓冲区并将数据写入磁盘。

    【讨论】:

      猜你喜欢
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-17
      • 2021-10-26
      • 2021-12-19
      • 1970-01-01
      • 2016-11-12
      相关资源
      最近更新 更多