为什么.NET F#程序无printfn语句时控制台日志无法正常显示?
问题根因
你遇到的是.NET控制台日志默认异步输出的特性导致的:
- 默认
Microsoft.Extensions.Logging.Console提供程序采用后台异步队列的方式输出日志,日志会先写入内存队列,由后台线程异步刷到控制台 - 你的程序逻辑非常轻量,
main函数执行完from "1"后直接返回0退出进程,后台线程还没来得及把队列里的日志输出到控制台,进程就被终止了 - 你取消注释
printfn的时候,printfn是同步阻塞写入控制台的操作,会给后台日志线程留出足够的时间完成日志刷写,所以能看到日志输出
正确修复方案
你可以选任意一种方式解决:
方案1:显式释放LoggerFactory(推荐)
LoggerFactory实现了IDisposable接口,释放时会自动等待所有队列中的日志完成刷写后再继续执行,修改代码如下:
open Microsoft.Extensions.Logging open Microsoft.Extensions.Logging.Console [<EntryPoint>] let main argv = // 把LoggerFactory的声明放到main里,用use关键字自动释放 use loggerFactory = LoggerFactory.Create(fun builder -> builder.AddConsole() |> ignore) let logger = loggerFactory.CreateLogger("test") let from whom = logger.LogInformation("hello " + whom) () do from "1" |> ignore // 退出前use绑定的loggerFactory会自动释放,等待日志刷完 0
方案2:将控制台日志设置为同步输出
修改日志配置,禁用异步队列模式,让日志直接同步输出到控制台:
let logger = LoggerFactory.Create(fun builder -> builder.AddConsole(fun opt -> opt.QueueMode = ConsoleLoggerQueueMode.Synchronous) |> ignore ).CreateLogger("test")
方案3:临时加延迟(仅调试用,不推荐生产环境)
在main退出前加极短的等待,给后台线程留足够时间输出日志:
[<EntryPoint>] let main argv = do from "1" |> ignore System.Threading.Thread.Sleep(10) // 等待10毫秒 0
内容的提问来源于stack exchange,提问作者err0r500
相关产品推荐
相关产品推荐

