Files
Dec2017-Script-Dump/mscorlib/System/Threading/Timer.cs
T
2026-06-04 11:42:34 +02:00

457 lines
21 KiB
C#

using System;
using System.Collections;
using System.Runtime.InteropServices;
namespace System.Threading
{
/// <summary>Provides a mechanism for executing a method at specified intervals. This class cannot be inherited.</summary>
/// <filterpriority>1</filterpriority>
// Token: 0x02000627 RID: 1575
[ComVisible(true)]
public sealed class Timer : MarshalByRefObject, IDisposable
{
/// <summary>Initializes a new instance of the Timer class, using a 32-bit signed integer to specify the time interval.</summary>
/// <param name="callback">A <see cref="T:System.Threading.TimerCallback" /> delegate representing a method to be executed. </param>
/// <param name="state">An object containing information to be used by the callback method, or null. </param>
/// <param name="dueTime">The amount of time to delay before <paramref name="callback" /> is invoked, in milliseconds. Specify <see cref="F:System.Threading.Timeout.Infinite" /> to prevent the timer from starting. Specify zero (0) to start the timer immediately. </param>
/// <param name="period">The time interval between invocations of <paramref name="callback" />, in milliseconds. Specify <see cref="F:System.Threading.Timeout.Infinite" /> to disable periodic signaling. </param>
/// <exception cref="T:System.ArgumentOutOfRangeException">The <paramref name="dueTime" /> or <paramref name="period" /> parameter is negative and is not equal to <see cref="F:System.Threading.Timeout.Infinite" />. </exception>
/// <exception cref="T:System.ArgumentNullException">The <paramref name="callback" /> parameter is null. </exception>
// Token: 0x060039CC RID: 14796 RVA: 0x000C6458 File Offset: 0x000C4658
public Timer(TimerCallback callback, object state, int dueTime, int period)
{
this.Init(callback, state, (long)dueTime, (long)period);
}
/// <summary>Initializes a new instance of the Timer class, using 64-bit signed integers to measure time intervals.</summary>
/// <param name="callback">A <see cref="T:System.Threading.TimerCallback" /> delegate representing a method to be executed. </param>
/// <param name="state">An object containing information to be used by the callback method, or null. </param>
/// <param name="dueTime">The amount of time to delay before <paramref name="callback" /> is invoked, in milliseconds. Specify <see cref="F:System.Threading.Timeout.Infinite" /> to prevent the timer from starting. Specify zero (0) to start the timer immediately. </param>
/// <param name="period">The time interval between invocations of <paramref name="callback" />, in milliseconds. Specify <see cref="F:System.Threading.Timeout.Infinite" /> to disable periodic signaling. </param>
/// <exception cref="T:System.ArgumentOutOfRangeException">The <paramref name="dueTime" /> or <paramref name="period" /> parameter is negative and is not equal to <see cref="F:System.Threading.Timeout.Infinite" />. </exception>
/// <exception cref="T:System.NotSupportedException">The <paramref name="dueTime" /> or <paramref name="period" /> parameter is greater than 4294967294. </exception>
// Token: 0x060039CD RID: 14797 RVA: 0x000C6470 File Offset: 0x000C4670
public Timer(TimerCallback callback, object state, long dueTime, long period)
{
this.Init(callback, state, dueTime, period);
}
/// <summary>Initializes a new instance of the Timer class, using <see cref="T:System.TimeSpan" /> values to measure time intervals.</summary>
/// <param name="callback">A <see cref="T:System.Threading.TimerCallback" /> delegate representing a method to be executed. </param>
/// <param name="state">An object containing information to be used by the callback method, or null. </param>
/// <param name="dueTime">The <see cref="T:System.TimeSpan" /> representing the amount of time to delay before the <paramref name="callback" /> parameter invokes its methods. Specify negative one (-1) milliseconds to prevent the timer from starting. Specify zero (0) to start the timer immediately. </param>
/// <param name="period">The time interval between invocations of the methods referenced by <paramref name="callback" />. Specify negative one (-1) milliseconds to disable periodic signaling. </param>
/// <exception cref="T:System.ArgumentOutOfRangeException">The number of milliseconds in the value of <paramref name="dueTime" /> or <paramref name="period" /> is negative and not equal to <see cref="F:System.Threading.Timeout.Infinite" />, or is greater than <see cref="F:System.Int32.MaxValue" />. </exception>
/// <exception cref="T:System.ArgumentNullException">The <paramref name="callback" /> parameter is null. </exception>
// Token: 0x060039CE RID: 14798 RVA: 0x000C6484 File Offset: 0x000C4684
public Timer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period)
{
this.Init(callback, state, (long)dueTime.TotalMilliseconds, (long)period.TotalMilliseconds);
}
/// <summary>Initializes a new instance of the Timer class, using 32-bit unsigned integers to measure time intervals.</summary>
/// <param name="callback">A <see cref="T:System.Threading.TimerCallback" /> delegate representing a method to be executed. </param>
/// <param name="state">An object containing information to be used by the callback method, or null. </param>
/// <param name="dueTime">The amount of time to delay before <paramref name="callback" /> is invoked, in milliseconds. Specify <see cref="F:System.Threading.Timeout.Infinite" /> to prevent the timer from starting. Specify zero (0) to start the timer immediately. </param>
/// <param name="period">The time interval between invocations of <paramref name="callback" />, in milliseconds. Specify <see cref="F:System.Threading.Timeout.Infinite" /> to disable periodic signaling. </param>
/// <exception cref="T:System.ArgumentOutOfRangeException">The <paramref name="dueTime" /> or <paramref name="period" /> parameter is negative and is not equal to <see cref="F:System.Threading.Timeout.Infinite" />. </exception>
/// <exception cref="T:System.ArgumentNullException">The <paramref name="callback" /> parameter is null. </exception>
// Token: 0x060039CF RID: 14799 RVA: 0x000C64B0 File Offset: 0x000C46B0
[CLSCompliant(false)]
public Timer(TimerCallback callback, object state, uint dueTime, uint period)
{
long num = (long)((dueTime != uint.MaxValue) ? ((ulong)dueTime) : ulong.MaxValue);
long num2 = (long)((period != uint.MaxValue) ? ((ulong)period) : ulong.MaxValue);
this.Init(callback, state, num, num2);
}
/// <summary>Initializes a new instance of the <see cref="T:System.Threading.Timer" /> class with an infinite period and an infinite due time, using the newly created <see cref="T:System.Threading.Timer" /> object as the state object. </summary>
/// <param name="callback">A <see cref="T:System.Threading.TimerCallback" /> delegate representing a method to be executed.</param>
// Token: 0x060039D0 RID: 14800 RVA: 0x000C64F4 File Offset: 0x000C46F4
public Timer(TimerCallback callback)
{
this.Init(callback, this, -1L, -1L);
}
// Token: 0x060039D2 RID: 14802 RVA: 0x000C6514 File Offset: 0x000C4714
private void Init(TimerCallback callback, object state, long dueTime, long period)
{
if (callback == null)
{
throw new ArgumentNullException("callback");
}
this.callback = callback;
this.state = state;
this.Change(dueTime, period, true);
}
/// <summary>Changes the start time and the interval between method invocations for a timer, using 32-bit signed integers to measure time intervals.</summary>
/// <returns>true if the timer was successfully updated; otherwise, false.</returns>
/// <param name="dueTime">The amount of time to delay before the invoking the callback method specified when the <see cref="T:System.Threading.Timer" /> was constructed, in milliseconds. Specify <see cref="F:System.Threading.Timeout.Infinite" /> to prevent the timer from restarting. Specify zero (0) to restart the timer immediately. </param>
/// <param name="period">The time interval between invocations of the callback method specified when the <see cref="T:System.Threading.Timer" /> was constructed, in milliseconds. Specify <see cref="F:System.Threading.Timeout.Infinite" /> to disable periodic signaling. </param>
/// <exception cref="T:System.ObjectDisposedException">The <see cref="T:System.Threading.Timer" /> has already been disposed. </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">The <paramref name="dueTime" /> or <paramref name="period" /> parameter is negative and is not equal to <see cref="F:System.Threading.Timeout.Infinite" />. </exception>
/// <filterpriority>2</filterpriority>
// Token: 0x060039D3 RID: 14803 RVA: 0x000C654C File Offset: 0x000C474C
public bool Change(int dueTime, int period)
{
return this.Change((long)dueTime, (long)period, false);
}
/// <summary>Changes the start time and the interval between method invocations for a timer, using <see cref="T:System.TimeSpan" /> values to measure time intervals.</summary>
/// <returns>true if the timer was successfully updated; otherwise, false.</returns>
/// <param name="dueTime">A <see cref="T:System.TimeSpan" /> representing the amount of time to delay before invoking the callback method specified when the <see cref="T:System.Threading.Timer" /> was constructed. Specify negative one (-1) milliseconds to prevent the timer from restarting. Specify zero (0) to restart the timer immediately. </param>
/// <param name="period">The time interval between invocations of the callback method specified when the <see cref="T:System.Threading.Timer" /> was constructed. Specify negative one (-1) milliseconds to disable periodic signaling. </param>
/// <exception cref="T:System.ObjectDisposedException">The <see cref="T:System.Threading.Timer" /> has already been disposed. </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">The <paramref name="dueTime" /> or <paramref name="period" /> parameter, in milliseconds, is less than -1. </exception>
/// <exception cref="T:System.NotSupportedException">The <paramref name="dueTime" /> or <paramref name="period" /> parameter, in milliseconds, is greater than 4294967294. </exception>
/// <filterpriority>2</filterpriority>
// Token: 0x060039D4 RID: 14804 RVA: 0x000C655C File Offset: 0x000C475C
public bool Change(TimeSpan dueTime, TimeSpan period)
{
return this.Change((long)dueTime.TotalMilliseconds, (long)period.TotalMilliseconds, false);
}
/// <summary>Changes the start time and the interval between method invocations for a timer, using 32-bit unsigned integers to measure time intervals.</summary>
/// <returns>true if the timer was successfully updated; otherwise, false.</returns>
/// <param name="dueTime">The amount of time to delay before the invoking the callback method specified when the <see cref="T:System.Threading.Timer" /> was constructed, in milliseconds. Specify <see cref="F:System.Threading.Timeout.Infinite" /> to prevent the timer from restarting. Specify zero (0) to restart the timer immediately. </param>
/// <param name="period">The time interval between invocations of the callback method specified when the <see cref="T:System.Threading.Timer" /> was constructed, in milliseconds. Specify <see cref="F:System.Threading.Timeout.Infinite" /> to disable periodic signaling. </param>
/// <exception cref="T:System.ObjectDisposedException">The <see cref="T:System.Threading.Timer" /> has already been disposed. </exception>
/// <filterpriority>2</filterpriority>
// Token: 0x060039D5 RID: 14805 RVA: 0x000C6580 File Offset: 0x000C4780
[CLSCompliant(false)]
public bool Change(uint dueTime, uint period)
{
long num = (long)((dueTime != uint.MaxValue) ? ((ulong)dueTime) : ulong.MaxValue);
long num2 = (long)((period != uint.MaxValue) ? ((ulong)period) : ulong.MaxValue);
return this.Change(num, num2, false);
}
/// <summary>Releases all resources used by the current instance of <see cref="T:System.Threading.Timer" />.</summary>
/// <filterpriority>2</filterpriority>
// Token: 0x060039D6 RID: 14806 RVA: 0x000C65B8 File Offset: 0x000C47B8
public void Dispose()
{
if (this.disposed)
{
return;
}
this.disposed = true;
Timer.scheduler.Remove(this);
}
/// <summary>Changes the start time and the interval between method invocations for a timer, using 64-bit signed integers to measure time intervals.</summary>
/// <returns>true if the timer was successfully updated; otherwise, false.</returns>
/// <param name="dueTime">The amount of time to delay before the invoking the callback method specified when the <see cref="T:System.Threading.Timer" /> was constructed, in milliseconds. Specify <see cref="F:System.Threading.Timeout.Infinite" /> to prevent the timer from restarting. Specify zero (0) to restart the timer immediately. </param>
/// <param name="period">The time interval between invocations of the callback method specified when the <see cref="T:System.Threading.Timer" /> was constructed, in milliseconds. Specify <see cref="F:System.Threading.Timeout.Infinite" /> to disable periodic signaling. </param>
/// <exception cref="T:System.ObjectDisposedException">The <see cref="T:System.Threading.Timer" /> has already been disposed. </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">The <paramref name="dueTime" /> or <paramref name="period" /> parameter is less than -1. </exception>
/// <exception cref="T:System.NotSupportedException">The <paramref name="dueTime" /> or <paramref name="period" /> parameter is greater than 4294967294. </exception>
/// <filterpriority>2</filterpriority>
// Token: 0x060039D7 RID: 14807 RVA: 0x000C65D8 File Offset: 0x000C47D8
public bool Change(long dueTime, long period)
{
return this.Change(dueTime, period, false);
}
// Token: 0x060039D8 RID: 14808 RVA: 0x000C65E4 File Offset: 0x000C47E4
private bool Change(long dueTime, long period, bool first)
{
if (dueTime > (long)((ulong)(-2)))
{
throw new ArgumentOutOfRangeException("Due time too large");
}
if (period > (long)((ulong)(-2)))
{
throw new ArgumentOutOfRangeException("Period too large");
}
if (dueTime < -1L)
{
throw new ArgumentOutOfRangeException("dueTime");
}
if (period < -1L)
{
throw new ArgumentOutOfRangeException("period");
}
if (this.disposed)
{
return false;
}
this.due_time_ms = dueTime;
this.period_ms = period;
long num;
if (dueTime == 0L)
{
num = 0L;
}
else if (dueTime < 0L)
{
num = long.MaxValue;
if (first)
{
this.next_run = num;
return true;
}
}
else
{
num = dueTime * 10000L + DateTime.GetTimeMonotonic();
}
Timer.scheduler.Change(this, num);
return true;
}
/// <summary>Releases all resources used by the current instance of <see cref="T:System.Threading.Timer" /> and signals when the timer has been disposed of.</summary>
/// <returns>true if the function succeeds; otherwise, false.</returns>
/// <param name="notifyObject">The <see cref="T:System.Threading.WaitHandle" /> to be signaled when the Timer has been disposed of. </param>
/// <exception cref="T:System.ArgumentNullException">The <paramref name="notifyObject" /> parameter is null. </exception>
/// <filterpriority>2</filterpriority>
// Token: 0x060039D9 RID: 14809 RVA: 0x000C66AC File Offset: 0x000C48AC
public bool Dispose(WaitHandle notifyObject)
{
if (notifyObject == null)
{
throw new ArgumentNullException("notifyObject");
}
this.Dispose();
NativeEventCalls.SetEvent_internal(notifyObject.Handle);
return true;
}
// Token: 0x04001754 RID: 5972
private const long MaxValue = 4294967294L;
// Token: 0x04001755 RID: 5973
private static Timer.Scheduler scheduler = Timer.Scheduler.Instance;
// Token: 0x04001756 RID: 5974
private TimerCallback callback;
// Token: 0x04001757 RID: 5975
private object state;
// Token: 0x04001758 RID: 5976
private long due_time_ms;
// Token: 0x04001759 RID: 5977
private long period_ms;
// Token: 0x0400175A RID: 5978
private long next_run;
// Token: 0x0400175B RID: 5979
private bool disposed;
// Token: 0x02000628 RID: 1576
private sealed class TimerComparer : IComparer
{
// Token: 0x060039DB RID: 14811 RVA: 0x000C66E8 File Offset: 0x000C48E8
public int Compare(object x, object y)
{
Timer timer = x as Timer;
if (timer == null)
{
return -1;
}
Timer timer2 = y as Timer;
if (timer2 == null)
{
return 1;
}
long num = timer.next_run - timer2.next_run;
if (num == 0L)
{
return 0;
}
return (num <= 0L) ? (-1) : 1;
}
}
// Token: 0x02000629 RID: 1577
private sealed class Scheduler
{
// Token: 0x060039DC RID: 14812 RVA: 0x000C6738 File Offset: 0x000C4938
private Scheduler()
{
this.list = new SortedList(new Timer.TimerComparer(), 1024);
new Thread(new ThreadStart(this.SchedulerThread))
{
IsBackground = true
}.Start();
}
// Token: 0x17000B1C RID: 2844
// (get) Token: 0x060039DE RID: 14814 RVA: 0x000C678C File Offset: 0x000C498C
public static Timer.Scheduler Instance
{
get
{
return Timer.Scheduler.instance;
}
}
// Token: 0x060039DF RID: 14815 RVA: 0x000C6794 File Offset: 0x000C4994
public void Remove(Timer timer)
{
if (timer.next_run == 0L || timer.next_run == 9223372036854775807L)
{
return;
}
lock (this)
{
this.InternalRemove(timer);
}
}
// Token: 0x060039E0 RID: 14816 RVA: 0x000C67FC File Offset: 0x000C49FC
public void Change(Timer timer, long new_next_run)
{
lock (this)
{
this.InternalRemove(timer);
if (new_next_run == 9223372036854775807L)
{
timer.next_run = new_next_run;
}
else if (!timer.disposed)
{
timer.next_run = new_next_run;
this.Add(timer);
if (this.list.GetByIndex(0) == timer)
{
Monitor.Pulse(this);
}
}
}
}
// Token: 0x060039E1 RID: 14817 RVA: 0x000C6890 File Offset: 0x000C4A90
private void Add(Timer timer)
{
int num = this.list.IndexOfKey(timer);
if (num != -1)
{
bool flag = long.MaxValue - timer.next_run > 20000L;
Timer timer2;
do
{
num++;
if (flag)
{
timer.next_run += 1L;
}
else
{
timer.next_run -= 1L;
}
if (num >= this.list.Count)
{
break;
}
timer2 = (Timer)this.list.GetByIndex(num);
}
while (timer2.next_run == timer.next_run);
}
this.list.Add(timer, timer);
}
// Token: 0x060039E2 RID: 14818 RVA: 0x000C6954 File Offset: 0x000C4B54
private int InternalRemove(Timer timer)
{
int num = this.list.IndexOfKey(timer);
if (num >= 0)
{
this.list.RemoveAt(num);
}
return num;
}
// Token: 0x060039E3 RID: 14819 RVA: 0x000C6984 File Offset: 0x000C4B84
private void SchedulerThread()
{
Thread.CurrentThread.Name = "Timer-Scheduler";
ArrayList arrayList = new ArrayList(512);
for (;;)
{
long timeMonotonic = DateTime.GetTimeMonotonic();
lock (this)
{
int num = this.list.Count;
for (int i = 0; i < num; i++)
{
Timer timer = (Timer)this.list.GetByIndex(i);
if (timer.next_run > timeMonotonic)
{
break;
}
this.list.RemoveAt(i);
num--;
i--;
ThreadPool.QueueUserWorkItem(new WaitCallback(timer.callback.Invoke), timer.state);
long period_ms = timer.period_ms;
long due_time_ms = timer.due_time_ms;
bool flag = period_ms == -1L || ((period_ms == 0L || period_ms == -1L) && due_time_ms != -1L);
if (flag)
{
timer.next_run = long.MaxValue;
}
else
{
timer.next_run = DateTime.GetTimeMonotonic() + 10000L * timer.period_ms;
arrayList.Add(timer);
}
}
num = arrayList.Count;
for (int i = 0; i < num; i++)
{
Timer timer2 = (Timer)arrayList[i];
this.Add(timer2);
}
arrayList.Clear();
this.ShrinkIfNeeded(arrayList, 512);
int capacity = this.list.Capacity;
num = this.list.Count;
if (capacity > 1024 && num > 0 && capacity / num > 3)
{
this.list.Capacity = num * 2;
}
long num2 = long.MaxValue;
if (this.list.Count > 0)
{
num2 = ((Timer)this.list.GetByIndex(0)).next_run;
}
int num3 = -1;
if (num2 != 9223372036854775807L)
{
long num4 = num2 - DateTime.GetTimeMonotonic();
num3 = (int)(num4 / 10000L);
if (num3 < 0)
{
num3 = 0;
}
}
Monitor.Wait(this, num3);
}
}
}
// Token: 0x060039E4 RID: 14820 RVA: 0x000C6BD8 File Offset: 0x000C4DD8
private void ShrinkIfNeeded(ArrayList list, int initial)
{
int capacity = list.Capacity;
int count = list.Count;
if (capacity > initial && count > 0 && capacity / count > 3)
{
list.Capacity = count * 2;
}
}
// Token: 0x0400175C RID: 5980
private static Timer.Scheduler instance = new Timer.Scheduler();
// Token: 0x0400175D RID: 5981
private SortedList list;
}
}
}