利用流写入器 WriteLineAsync 和 WhenAll 是否正确

All*_*ool 0 c# asynchronous streamwriter async-await

我有一段代码以异步方式写入内存流(.NET Standard 2.1)

  • 创建热任务列表,每行一个
  • 然后等待全部完成
  • 最后将写入器缓冲区刷新到内存流

代码:

await using var memoryStream = new MemoryStream();
await using var writer = new StreamWriter(memoryStream);

var recordTasks = stringRecordsToWrite.Select(r => writer.WriteLineAsync(r));

await Task.WhenAll(recordTasks);

await writer.FlushAsync();

var result = memoryStream.ToArray();
Run Code Online (Sandbox Code Playgroud)

问题

有几个问题困扰着我:

  1. 有报道称,一些记录有时会被跳过。因此,我想知道这样的实施是否是根本原因。我尝试在本地重现该问题,但不幸的是没有成功
  2. Resharper 还强调,“writer”(在 SELECT 语句内)是一个捕获的变量,并在外部作用域中进行处理。这会是一个问题吗?

或者那些都是假痕迹,而且实现得很好,我应该尝试在其他地方找到原因

Ps代码片段,用于尝试重现该问题,但是,结果文件大小约为 250 MB,并且仍然没有该问题的证据......

 internal class Program
    {
        public static async Task Main(string[] args)
        {
            var records = new Dictionary<string, IEnumerable<RecordsToWrite>>();

            for (var i = 0; i < 200; i++)
            {
                var recordKey = $"test-{i}";

                records.Add(recordKey, default);

                var itemRecords = new List<RecordsToWrite>();

                for (var x = 0; x < 500; x++)
                {
                    itemRecords.Add(new RecordsToWrite
                    {
                        Tracking = $"{recordKey}-Track-Ref-{x}"
                    });
                }

                records[recordKey] = itemRecords;
            }


            var resultAsBytes = new List<byte>();
            var randomizer = new Random();

            foreach (var kv in records)
            {
                await using var memoryStream = new MemoryStream();
                await using var writer = new StreamWriter(memoryStream);

                var recordsToWrite = kv.Value;

                var writingRecordsTasks = recordsToWrite.Select(x =>
                {
                    var randomLengthString = randomizer.Next(100, 5000);

                    return writer.WriteLineAsync($"track-ref-{x.Tracking}, " +
                                                 $"now in ticks: {DateTime.UtcNow.Ticks}, " +
                                                 $"content: {new string(GetRandomLetter(), randomLengthString)}");
                });

                await Task.WhenAll(writingRecordsTasks);

                await writer.FlushAsync();

                resultAsBytes.AddRange(memoryStream.ToArray());
            }

            var content = Encoding.UTF8.GetString(resultAsBytes.ToArray());
            await File.WriteAllLinesAsync("PathToAFile.txt", new[] { content });

            Console.ReadLine();
        }

        public static char GetRandomLetter() => (char)('a' + new Random().Next(0, 26));
    }
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 5

您只有一个流。并行异步写入实际上没有意义 - 很多事情都可能出错。我什至不知道MemoryStream线程安全是什么样的,也看不到任何相关文档。文档明确指出StreamWriter

默认情况下,StreamWriter 不是线程安全的。请参阅 TextWriter.Synchronized 了解线程安全包装器。

我强烈建议您按顺序迭代,例如

foreach (var item in stringRecordsToWrite)
{
    await writer.WriteLineAsync(item);
}
Run Code Online (Sandbox Code Playgroud)