Can I use Threading.Timer in its callback?

I am using Threading.Timer , for example:

 new Timer(new TimerCallback(y=> { try { Save(Read(DateTime.Now)); // here i want to dispose this timer } catch { } }),null,100000,10000); 

How can I set this timer inside the callback. or a workaround? Update: Let me explain the situation. I want to try calling the Save method while it throws an exception. If this works, I need to stop the timer.

+4
source share
5 answers

Try the following:

 Timer timer = null; timer = new Timer(new TimerCallback(y => { try { Save(Read(DateTime.Now)); // here i want to dispose this timer timer.Dispose(); } catch { } })); timer.Change(10000, 10000); 

EDIT:

I modified the code a bit according to Chuu's suggestion. Note that if TimerCallback is called simultaneously by different timer events, Timer.Dispose can be called multiple times. Fortunately, Timer does not care if it is removed several times.

+14
source

Here is the best way to do this. When you use a constructor with only one parameter (TimerCallback), the state passed to the callback will be the timer itself.

 Timer timer = new Timer(o => { ((Timer)o).Dispose(); //Your code here }); //Start the timer timer.Change(100000,10000); 

Here is an example from msdn docs:

 public void StartTimer(int dueTime) { Timer t = new Timer(new TimerCallback(TimerProc)); t.Change(dueTime, 0); } private void TimerProc(object state) { // The state object is the Timer object. Timer t = (Timer) state; t.Dispose(); Console.WriteLine("The timer callback executes."); } 

http://msdn.microsoft.com/en-us/library/ms149618(v=vs.110).aspx

+2
source

You need to save the timer link in a variable -

 public class MyClass { private Timer _timer; public void StartTimer() { _timer = new Timer(new TimerCallback(y=>{ try { Save(Read(DateTime.Now)); _timer.Dispose(); } catch { } }),null,100000,10000); } } 

Note. This is unverified code. Check if it works and updates.

+1
source

You will need to store the timer reference somewhere and pass this as a state to the timer object itself. Try creating a class like this:

 public class TimerContainer { public Timer Timer { get; set; } } 

Then use it in your method as follows:

 Action<object> tcb = state => { var container = (TimerConatiner)state; try { Save(Read(DateTime.Now)); container.Timer.Dispose(); } catch { // whatever... } }; var container = new TimerContainer(); container.Timer = new Timer(tcb, container, 100000, 10000); 
0
source

Be careful if you use multithreading or multitasking! If so, here you are code and a means to extend the ExpAfter method (.net 4.0):

  private static object syncObj = new object(); public static void CancelAfter(this CancellationTokenSource source, int timeoutMilliseconds, Action code = null) { if (timeoutMilliseconds == 0) return; // No timeout if (source == null) { throw new NullReferenceException(); } if (timeoutMilliseconds < -1) { throw new ArgumentOutOfRangeException("timeout"); } Timer timer = new Timer(delegate(object self) { lock (syncObj) { try { if (null != code) code.Invoke(); source.Cancel(); ((IDisposable)self).Dispose(); } catch (ObjectDisposedException) { } } }); timer.Change(timeoutMilliseconds, -1); } } 

Regards, Juanlu, ElGuerre

0
source

Source: https://habr.com/ru/post/1342785/


All Articles