【发布时间】:2019-04-18 12:01:10
【问题描述】:
在通过多个线程将日志写入数据库时,我注意到 Nlog 存在一个奇怪的问题。
问题是一个数据库的日志有时会添加到另一个数据库中,即它们有时是混合的。更新 Nlog 的 DbTarget 的方法不是线程安全的还是我在这里做错了什么? 请分享您应对此问题的想法/经验。
我正在为三个不同的客户使用同一个应用程序,每个客户在同一服务器上拥有三个不同的数据库。我有 C# windows 应用程序,其中为 3 个不同的数据库创建了 3 个线程。每个线程都以如下所示的方式处理自己的数据库:
public void StartService()
{
string conn1 = connectionstring for database1;
string conn2 = connectionstring for database2;
Thread ThreadDB1 = new Thread(new ThreadStart(() => Process(conn1)));
Thread ThreadDB2 = new Thread(new ThreadStart(() => Process(conn2)));
ThreadDB1.Start();
ThreadDB2.Start();
}
public void Process(string domainCon)
{
this.isActive = true;
while (this.isActive)
{
try
{
StartOperation(domainCon);
}
catch (Exception ex)
{
//since the Nlog has not been initialised for an individual threads that switch per database,
//If any error occurs here, log that in event log instead
EventLog.WriteEntry("Application", ex.ToString(), EventLogEntryType.Error);
}
}
}
public static void StartOperation(string domainCon)
{
NLogLoggerService loggerService;
NLogLogger Logger;
/* Set the "NEW" instance of logger here so that each instance
* will be per thread (i.e per database) */
Logger = new NLogLogger("MyAppName_Processor");
loggerService = new NLogLoggerService(Logger);
//create the DbTarget that is passed by current thread
Logger.UpdateNLogDatabase(domainCon);
// the process to select the records from Db happens here
ProcessDbRecords(domainCon);
}
ProcessDbRecords(domainCon)
{
//Records are selected, analyzed processed and saved again in database for each thread
//the following log is written in database but log of one database is written in another database sometimes
loggerService.LoggerInfo("The Database has been called for connString: " + domainCon);
}
//in LogService class, i have a method that updates the database target with connectionstring provided in runtime:
public static void UpdateNLogDatabase(string connString)
{
var config = LogManager.Configuration;
var dbTarget = (Targets.DatabaseTarget)config.FindTargetByName("Database");
dbTarget.ConnectionString = connString;
LogManager.ReconfigExistingLoggers();
}
【问题讨论】:
-
据我了解,您正在更改全局配置,因此它将影响所有记录器(我的意思是,该方法名为
ReconfigExistingLoggers,所以它有点放弃了)。因此,更改 dbtarget 的连接字符串的线程将影响其他线程。我认为您需要为每个记录器使用不同的目标 -
嗨@KevinGosse,谢谢你的回复。您能否提供一些详细信息,我如何为每个记录器实现不同的目标?
标签: c# asp.net multithreading thread-safety nlog