1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
| using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;
namespace FrameWork
{
public class MonTimer : IDisposable
{
int m_interval;
public int Interval
{
get { return m_interval; }
set {
if (m_interval < 0)
throw new ArgumentOutOfRangeException("Un thread ne peut pas avoir un interval de temps < 0");
m_interval = value; }
}
private bool m_Enabled;
readonly object lockgetter = new object();
readonly object locksetter = new object();
public bool Enable
{
get
{
lock (lockgetter)
{
m_enableLocker.WaitOne();
return m_Enabled;
}
}
set
{
bool old;
lock (locksetter)
{
m_enableLocker.Reset();
old = m_Enabled;
m_Enabled = value;
m_enableLocker.Set();
}
if (old != m_Enabled)
{
if (!m_Enabled)
Stop();
else
Start();
}
}
}
Thread m_thread;
EventWaitHandle m_enableLocker;
public event EventHandler Tick;
readonly object lockStart = new object();
public void Start()
{
lock (lockStart)
{
if (m_thread == null)
{
m_thread = new Thread(Run);
m_thread.Name = "(MonTimer) "+m_threadName;
m_thread.IsBackground = true;
Enable = true;
m_thread.Start();
}
}
}
readonly object lockStop = new object();
public void Stop()
{
lock (lockStop)
{
this.Enable = false;
if (m_thread != null)
{
if (m_thread != Thread.CurrentThread)
{
m_thread.Join(10000 + m_interval);
if (m_thread.IsAlive)
{
try
{
m_thread.Interrupt();
}
catch
{
}
String errmsg = String.Format("Le Thread '{0}' n'a pas su s'arretter apres 30 Secondes malgrés la demande d'interruption", m_thread.Name);
m_thread = null;
throw new ThreadInterruptedException(errmsg);
}
m_thread = null;
}
else //Si c'est le thread lui meme qui demande à se terminer on va créer un watcher
new Thread(delegate() { Stop(); }); //Ce thread annonyme jetera une exception dans Stop si le thread en cours ne se termine pas dans les 30 secondes
}
}
}
String m_threadName;
private static readonly object s_lockConstruct = new object();
public MonTimer(String nom)
{
lock (s_lockConstruct)
{
if (String.IsNullOrEmpty(nom))
throw new ArgumentOutOfRangeException("Le thread du timer doit forcement comporter un nom");
m_interval = 0;
m_threadName = nom;
Init();
}
}
public MonTimer(String nom,int interval)
{
lock (s_lockConstruct)
{
if (String.IsNullOrEmpty(nom))
throw new ArgumentOutOfRangeException("Le thread du timer doit forcement comporter un nom");
m_interval = interval;
m_threadName = nom;
Init();
}
}
private void Init()
{
m_Enabled = true;
m_enableLocker = new EventWaitHandle(true, EventResetMode.ManualReset);
}
private void Run()
{
Stopwatch m_chrono = new Stopwatch();
do
{
m_chrono.Reset();
m_chrono.Start();
if (Tick != null)
Tick(this, EventArgs.Empty);
m_chrono.Stop();
int delay = m_interval - (int)m_chrono.ElapsedMilliseconds;
if (delay > 0)
Thread.Sleep(delay);
} while (this.Enable);
}
#region IDisposable Members
public void Dispose()
{
try
{
Stop();
}
catch { }
}
#endregion
public override string ToString()
{
return String.Format("({0}) : {1}", this.GetType(), m_threadName);
}
}
} |
Partager