Timer callback is lost if NLog Logger is defined

3 messages Options
Embed this post
Permalink
Corin

Timer callback is lost if NLog Logger is defined

Reply Threaded More More options
Print post
Permalink
Coworkers and I tracked down an issue today that has us baffled.  If anyone can provide any insight, we'd love to hear it.

In a windows forms project (VS 2005 and 2008 at least) if you create a new timer and callback object with local variables, and an instance of an NLog Logger has been defined, eventually the callback stops being activated.

In other words, the timer will start up, and activate the callback on its interval for a certain number of iterations (varies by which machine you use, doesn't seem to matter what time interval the timer has set) and then the callback stops being called.  On my machine it runs about 6 or 7 iterations, others it runs 5, others it runs 12.

This happens whether the callback method is calling a logger method or not, however if you comment out the logger instance entirely, the timer and callback work properly indefinitely.

If, however, you define the references to the timer and callback as member variables rather than local, everything seems to play nicely.

What we can't figure out is why NLog is making this happen, particularly when all you have to do is DEFINE a logger, not even use it.


Here is the code that FAILS:

using System;
using System.Windows.Forms;
using NLog;
namespace WindowsFormsApplication6
{
	public partial class Form1 : Form
	{
		private Logger Log = LogManager.GetLogger( "" );
		private int iCount = 0;

		public Form1()
		{
<nabble_a href="WindowsFormsApplication6.zip">WindowsFormsApplication6.zip</nabble_a><nabble_a href="NLog.config">NLog.config</nabble_a>			InitializeComponent();

			System.Threading.TimerCallback tcb = new System.Threading.TimerCallback(callback);
			System.Threading.Timer t = new System.Threading.Timer(tcb, null, 0, 10);
		}

		private void callback( object o )
		{
			++iCount;
			Log.Trace( "iCount {0}", iCount ); // Fails with or without this line
			Console.WriteLine( "iCount {0}", iCount );
		}
	}
}


This code works, because NLog has been removed entirely:

using System;
using System.Windows.Forms;
using NLog;

namespace WindowsFormsApplication6
{
	public partial class Form1 : Form
	{
		private int iCount = 0;

		public Form1()
		{
			InitializeComponent();

			System.Threading.TimerCallback tcb = new System.Threading.TimerCallback(callback);
			System.Threading.Timer t = new System.Threading.Timer(tcb, null, 0, 1);
		}

		private void callback( object o )
		{
			++iCount;
			Console.WriteLine( "iCount {0}", iCount );
		}
	}
}



And this code is the final solution that works WITH NLog because the variables are members rather than local to the construtor method:

using System;
using System.Windows.Forms;
using NLog;

namespace WindowsFormsApplication6
{
	public partial class Form1 : Form
	{
		private Logger Log = LogManager.GetLogger( "" );
		private int iCount = 0;
		System.Threading.TimerCallback tcb = null;
		System.Threading.Timer t = null;

		public Form1()
		{
			InitializeComponent();

			tcb = new System.Threading.TimerCallback(callback);
			t = new System.Threading.Timer(tcb, null, 0, 1);
		}

		private void callback( object o )
		{
			++iCount;
			Log.Trace( "iCount {0}", iCount );
			Console.WriteLine( "iCount {0}", iCount );
		}
	}
}



Here is the NLog.config file we are using (we've played around with different config settings to no avail, and nlog is not producing an internal error log):

<?xml version="1.0" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      internalLogFile="${basedir}/logs/nlogInternal.txt"
      internalLogLevel="Warn" >

  <targets async="false">

    <target name="file"
            xsi:type="File"
            fileName="${basedir}/MyLog.log"
			layout="${longdate}: ${message}"
            keepFileOpen="false"
            encoding="iso-8859-2" />

  </targets>

  <rules>
    <logger name="*" minlevel="Trace" writeTo="file" />
  </rules>
</nlog>



If anyone can provide some insight into WHY this is happening, we would appreciate it.  I tried to attached a zip file with the actual project, but that doesn't seem to be working properly....

Thanks,

Corin
Jaroslaw Kowalski

Re: Timer callback is lost if NLog Logger is defined

Reply Threaded More More options
Print post
Permalink
I will investigate this, in the meantime can you please file a bug on nlog.codeplex.com ?
 
My first idea is that NLog's timer (which is used to watch for configuration file changes) somehow interferes with your timer. Can you try disabling autoReload="true" from NLog.config or removing NLog.config altogether?
 
Jarek
On Thu, Oct 1, 2009 at 11:42 AM, Corin (via Nabble) <[hidden email]> wrote:
Coworkers and I tracked down an issue today that has us baffled.  If anyone can provide any insight, we'd love to hear it.

In a windows forms project (VS 2005 and 2008 at least) if you create a new timer and callback object with local variables, and an instance of an NLog Logger has been defined, eventually the callback stops being activated.

In other words, the timer will start up, and activate the callback on its interval for a certain number of iterations (varies by which machine you use, doesn't seem to matter what time interval the timer has set) and then the callback stops being called.  On my machine it runs about 6 or 7 iterations, others it runs 5, others it runs 12.

This happens whether the callback method is calling a logger method or not, however if you comment out the logger instance entirely, the timer and callback work properly indefinitely.

If, however, you define the references to the timer and callback as member variables rather than local, everything seems to play nicely.

What we can't figure out is why NLog is making this happen, particularly when all you have to do is DEFINE a logger, not even use it.


Here is the code that FAILS:

using System;
using System.Windows.Forms;
using NLog;
namespace WindowsFormsApplication6
{
	public partial class Form1 : Form
	{
		private Logger Log = LogManager.GetLogger( "" );
		private int iCount = 0;

		public Form1()
		{
<nabble_a href="WindowsFormsApplication6.zip">WindowsFormsApplication6.zip</nabble_a><nabble_a href="NLog.config">NLog.config</nabble_a>			InitializeComponent();

			System.Threading.TimerCallback tcb = new System.Threading.TimerCallback(callback);
			System.Threading.Timer t = new System.Threading.Timer(tcb, null, 0, 10);
		}

		private void callback( object o )
		{
			++iCount;
			Log.Trace( "iCount {0}", iCount ); // Fails with or without this line
			Console.WriteLine( "iCount {0}", iCount );
		}
	}
}


This code works, because NLog has been removed entirely:

using System;
using System.Windows.Forms;
using NLog;

namespace WindowsFormsApplication6
{
	public partial class Form1 : Form
	{
		private int iCount = 0;

		public Form1()
		{
			InitializeComponent();

			System.Threading.TimerCallback tcb = new System.Threading.TimerCallback(callback);
			System.Threading.Timer t = new System.Threading.Timer(tcb, null, 0, 1);
		}

		private void callback( object o )
		{
			++iCount;
			Console.WriteLine( "iCount {0}", iCount );
		}
	}
}



And this code is the final solution that works WITH NLog because the variables are members rather than local to the construtor method:

using System;
using System.Windows.Forms;
using NLog;

namespace WindowsFormsApplication6
{
	public partial class Form1 : Form
	{
		private Logger Log = LogManager.GetLogger( "" );
		private int iCount = 0;
		System.Threading.TimerCallback tcb = null;
		System.Threading.Timer t = null;

		public Form1()
		{
			InitializeComponent();

			tcb = new System.Threading.TimerCallback(callback);
			t = new System.Threading.Timer(tcb, null, 0, 1);
		}

		private void callback( object o )
		{
			++iCount;
			Log.Trace( "iCount {0}", iCount );
			Console.WriteLine( "iCount {0}", iCount );
		}
	}
}



If anyone can provide some insight into WHY this is happening, we would appreciate it.  I have attached a zip file with the actual project, as well as the nlog.config file we are using (we've played around with different config settings to no avail, and nlog is not producing an internal error log).

Thanks,

Corin

Corin

Re: Timer callback is lost if NLog Logger is defined

Reply Threaded More More options
Print post
Permalink
Thanks for the reply, Jarek.

Posted as a bug on codeplex.

Setting autoReload="false" (or removing it) didn't seem to help at all, but removing the config file altogether seemed to make it behave as it should (although without nlog logging, of course...)