异步写入文件会导致行数不正确和内容不正确

时间:2017-07-31 16:27:28

标签: .net asynchronous logging

我有一个小的记录器类,它只包含一些静态帮助器方法,可以轻松写入日志文件。我想测试它有多强大,所以我试图一次异步运行它100次。

[TestMethod]
public void Diagnostics_AsyncWritePass()
{
    int linesToWrite = 100;
    String logMsg = "Async test log ";
    List<Task> asyncTaskList = new List<Task>();

    for (int i = 0; i < linesToWrite; i++)
    {
        Task task = new Task(() => Logger.Info(logMsg + i));
        asyncTaskList.Add(task);
        task.Start();
    }

    Task.WaitAll(asyncTaskList.ToArray());

    List<String> lines = GetLastLogLines(linesToWrite);

    foreach (String line in lines)
    {
        Assert.IsTrue(line.Contains(logMsg));
    }
}

实际记录(在Logger.Info方法内)使用:

执行
File.AppendAllText(LogPath, logMsg + Environment.NewLine);

GetLastLogLines方法是:

private List<String> GetLastLogLines(int numLines)
{
    List<String> lines = File.ReadLines(Logger.LogPath)
        .Reverse()
        .Take(numLines)
        .ToList();
    return lines;
}

但是,我有两个问题。

  • 首先是它不是写100行,而是写作90左右。
  • 第二个是每一行都是Async test log 100 - 数字不会每行增加。我猜测i计数器是通过引用传递的,而不是通过值传递的。

为什么会出现这些问题?

修改 通过替换GetLastLogLines的内容解决了错误的行数问题。以前,它使用File.ReadLines然后使用LINQ只占用x行。相反,我使用了this answer并返回了正确的行数。

1 个答案:

答案 0 :(得分:0)

当lambda表达式捕获迭代变量时,第二个问题是标准问题。

进行以下更改。

for (int i = 0; i < linesToWrite; i++)
{
    var t = i;
    Task task = new Task(() => Logger.Info(logMsg + t));
    asyncTaskList.Add(task);
    task.Start();
}

您能告诉我们GetLastLogLines()的作用吗?