Click here to Skip to main content
15,887,596 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
Hi,

I am a little confused by the System.Threading.Timer class. The following code compiles and runs fine:

C#
using System;
using System.Threading;

namespace ConsoleApplication1
{
	public class Repeater
	{
		public Repeater( Action<object> callback, object state )
		{
			// Timer takes a TimerCallback delegate, but this constructor takes an Action<object>.  I have
			// read the easiest way to 'cast' a delegate is using lambdas.  Like this:
			TimerCallback tcb = ( s ) => callback( s );

			// So now I can construct my Timer.
			_timer = new Timer( tcb, state, 0, 5000 );
		}

		private Timer _timer = null;
	}

	public class Program
	{
		static void Main( string[] args )
		{
			Action<object> callback = MyFunction;
			Repeater repeater = new Repeater( callback, _count );

			Console.ReadKey();
		}

		private static void MyFunction( object state )
		{
			Console.WriteLine( $"event...{(int)state}" );
		}

		private static int _count = 42;
	}
}


Every 5 seconds, it prints out "event...42".

When I read the MSDN documentation on Timer (Timer Constructor (TimerCallback, Object, Int64, Int64) (System.Threading)), it says that the state parameter is: "An object containing information to be used by the callback method." This implies I can somehow pass information into the callback function each time it is called. So, in my example above, I could find a way to get the callback to print out 42...43...44... etc.

Is there any way to do this, or is the state parameter usable only as a way to specify some kind of initial state for the callback delegate (as I have done here, by effectively saying, "Start counting from 42")?

Kind wishes ~ Patrick

What I have tried:

The code example given. I just can't work out how to write anything that does "more" than what I am doing already.
Posted
Updated 5-Apr-16 5:26am
v3

1 solution

I am not sure if it is the only or best solution, but the following code achieves what I was looking to do. Basically, all I have done is changed the "dumb" integer _count variable to a class, which means it is passed by reference and it can maintain its own internal state, like this:

C#
using System;
using System.Threading;

namespace ConsoleApplication1
{
	public class Repeater
	{
		public Repeater( Action<object> callback, object state )
		{
			// Time takes a TimerCallback delegate, but this constructor takes an Action<object>.  I have
			// read the easiest way to 'cast' a delegate is using lambdas.  Like this:
			TimerCallback tcb = ( s ) => callback( s );

			// So now I can construct my Timer.
			_timer = new Timer( tcb, state, 0, 5000 );
		}

		private Timer _timer = null;
	}

	public class Counter
	{
		public int Count { get; set; }
	}

	public class Program
	{
		static void Main( string[] args )
		{
			Counter counter = new Counter();
			Action<object> callback = MyFunction;
			Repeater repeater = new Repeater( callback, counter );

			Console.ReadKey();
		}

		private static void MyFunction( object state )
		{
			Counter counter = state as Counter;
			Console.WriteLine( $"event...{counter.Count}" );
			counter.Count = counter.Count + 1;
		}
	}
}


This seems to work. I would still appreciate any comments though.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900