在以下代码中,程序在日志完全刷新之前终止:
class Program
{
static void Main(string[] args)
{
var count = -1;
var tasks = new ConcurrentBag<Task>();
var services = new ServiceCollection();
services.AddLogging(configure => configure.AddConsole());
var serviceProvider = services.BuildServiceProvider();
var logger = serviceProvider.GetService<ILogger<Program>>();
if (logger is null)
throw new NullReferenceException();
Parallel.ForEach(Enumerable.Range(0, 1000), i =>
{
tasks.Add(Task.Run(() => logger.LogInformation(Interlocked.Increment(ref count).ToString())));
//tasks.Add(Task.Run(() => Console.WriteLine(Interlocked.Increment(ref count).ToString())));
});
Task.WhenAll(tasks).Wait();
}
}即使应该打印1.000条日志语句,但只会刷新以下内容:
info: Net5.Program[0]
6
info: Net5.Program[0]
2
info: Net5.Program[0]
5
info: Net5.Program[0]
1
info: Net5.Program[0]
7
info: Net5.Program[0]
4
info: Net5.Program[0]
3
info: Net5.Program[0]
0
info: Net5.Program[0]
8
info: Net5.Program[0]
10
C:\Users\MyName\source\repos\ConsoleApp\Net5\bin\Debug\net5.0\Net5.exe (process 28048) exited with code 0.
Press any key to close this window . . .然而,当使用Console.WriteLine (在上面的代码中注释掉)时,所有的行都会被打印出来,这导致人们怀疑控制台记录器在幕后是异步的。
如何确保等待所有日志语句而不需要手动延迟?
编辑:
我决定使用以下代码,这就达到了目的:
class Program
{
static void Main(string[] args)
{
var count = -1;
var services = new ServiceCollection();
services.AddLogging(configure => configure.AddConsole());
using var serviceProvider = services.BuildServiceProvider();
var logger = serviceProvider.GetRequiredService<ILogger<Program>>();
var tasks = Enumerable.Range(0, 50000)
.AsParallel()
.Select(_ => Task.Run(() => logger.LogInformation(Interlocked.Increment(ref count).ToString())));
Task.WhenAll(tasks).Wait();
}
}主要区别:
GetRequiredService获取ILogger实例以避免空检查。Enumerable.Range(...).AsParallel.Select(...)代替Parallel.ForEach来始终坚持执行任务。H 215F 216发布于 2021-09-29 18:38:59
如果您释放服务提供者,它将释放所有的单例服务,这将刷新记录器。
也没有必要使用Parallel.ForEach。实际上,将Parallel.ForEach与async``await结合使用是一种代码嗅探。这几乎总是错的。
而且,由于您标记了问题.NET 5.0,您可以将代码更改为:
class Program
{
static async Task Main()
{
var count = -1;
var tasks = new ConcurrentBag<Task>();
var services = new ServiceCollection();
services.AddLogging(configure => configure.AddConsole());
using var serviceProvider = services.BuildServiceProvider();
var logger = serviceProvider.GetRequiredService<ILogger<Program>>();
for (var i = 0; i < 1000; i++)
{
tasks.Add(Task.Run(() => logger.LogInformation(Interlocked.Increment(ref count).ToString())));
};
await Task.WhenAll(tasks);
}
}https://stackoverflow.com/questions/69381601
复制相似问题