【发布时间】:2020-06-09 09:45:15
【问题描述】:
我们有一个日志系统,我们使用Log.Info 并写入ILogger。
现在我们有多个工作人员在后台运行,我们希望这些工作人员写入自己的日志。因此,每个 Worker 都捆绑了所有内容。执行此任务时记录的所有内容都应转发到其自己的记录器。
我们正在考虑创建一个方法 Log.SetLoggerForCurrentThread,用 ThreadLocal 实现它。执行代码如下所示:
public class Worker
{
ILogger _Logger;
public void ExecuteTask()
{
Log.Info( "This goes to the 'Global' logger" );
using ( Log.SetLoggerForCurrentThread(_Logger) )
{
Log.Info( "This goes to local logger" );
DoWork();
}
}
private async void DoWork()
{
Log.Info( "Starting..." );
// SomeMethod does some logging,
// that also needs to be forwared to the local logger
var value = await SomeDeepDomainClass.SomeMethod();
// if we use ThreadLocal, and this thread has been reused,
// it could be a completely different logger that is now attached.
Log.Info( "Ended..." );
}
}
问题
- 当我们使用 await 时,理论上线程可以处理另一个工作线程,从而混淆本地记录器。
- 做类似事情的最佳模式是什么?我可以使用什么存储方式?
-
CultureInfo如何处理这个问题?
背景信息
这些 Worker 中的大多数将在 Azure WorkerRole 实例中运行,但有时它们也会被控制台应用程序触发(一次)。
【问题讨论】:
-
CultureInfo设置在每个托管线程的开头——独立于Task。如果您想从Task登录,我建议显式使用Log.SetLoggerForCurrentThread。它表明您已经明确考虑到这一点并进行了补偿。 -
在我开始回答之前,您应该知道 log4net 是免费的,并且已经解决了您的大部分问题。
-
嗨@GuillaumeCR,您可能是对的,但将其视为类似模式的一般编程问题。
-
@PeterRitchie,在代码完成 5 秒后,初级程序员会介入并在所有等待的任务(甚至只是其中的几个 - 应该足以如果记录器是线程本地的,则降低整个记录生态系统。
-
在工作线程上运行的代码中使用 async/await 的附加值会显着下降。它已经异步运行,使用 await 只会增加开销。像这样的问题,它会出错,因为继续在另一个线程上运行。这不是免费的。请记住,CultureInfo 也不会流动,这是 .NET 中的一个臭名昭著的问题。
标签: c# multithreading async-await