Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / WinForms / Managed / System / WinForms / Timer.cs / 1 / Timer.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
/*
*/
namespace System.Windows.Forms {
using System.Threading;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Diagnostics;
using System.Windows.Forms.Design;
using System;
using System.Globalization;
///
///
/// Implements a Windows-based timer that raises an event at user-defined intervals. This timer is optimized for
/// use in Win Forms
/// applications and must be used in a window.
///
[
DefaultProperty("Interval"),
DefaultEvent("Tick"),
ToolboxItemFilter("System.Windows.Forms"),
SRDescription(SR.DescriptionTimer)
]
public class Timer : Component {
///
///
///
private int interval;
///
///
///
private bool enabled;
///
///
///
private EventHandler onTimer;
///
///
///
private GCHandle timerRoot;
// our holder for the HWND that handles our Timer messages.
//
private TimerNativeWindow timerWindow;
///
///
///
private object userData;
private object syncObj = new object();
///
///
/// Initializes a new instance of the
/// class.
///
public Timer()
: base() {
interval = 100;
}
///
///
/// Initializes a new instance of the class with the specified container.
///
public Timer(IContainer container) : this() {
container.Add(this);
}
///
[
SRCategory(SR.CatData),
Localizable(false),
Bindable(true),
SRDescription(SR.ControlTagDescr),
DefaultValue(null),
TypeConverter(typeof(StringConverter)),
]
public object Tag {
get {
return userData;
}
set {
userData = value;
}
}
///
///
/// Occurs when the specified timer
/// interval has elapsed and the timer is enabled.
///
[SRCategory(SR.CatBehavior), SRDescription(SR.TimerTimerDescr)]
public event EventHandler Tick {
add {
onTimer += value;
}
remove {
onTimer -= value;
}
}
///
///
///
/// Disposes of the resources (other than memory) used by the timer.
///
///
protected override void Dispose(bool disposing) {
if (disposing) {
if (timerWindow != null) {
timerWindow.StopTimer();
}
Enabled = false;
}
timerWindow = null;
base.Dispose(disposing);
}
///
///
/// Indicates whether the timer is
/// running.
///
[
SRCategory(SR.CatBehavior),
DefaultValue(false),
SRDescription(SR.TimerEnabledDescr)
]
public virtual bool Enabled {
get {
if (timerWindow == null) {
return enabled;
}
return timerWindow.IsTimerRunning;
}
set {
lock(syncObj) {
if (enabled != value) {
enabled = value;
// At runtime, enable or disable the corresponding Windows timer
//
if (!DesignMode) {
if (value) {
// create the timer window if needed.
//
if (timerWindow == null) {
timerWindow = new TimerNativeWindow(this);
}
timerRoot = GCHandle.Alloc(this);
timerWindow.StartTimer(interval);
}
else{
if (timerWindow != null){
timerWindow.StopTimer();
}
if (timerRoot.IsAllocated) {
timerRoot.Free();
}
}
}
}
}
}
}
///
///
///
/// Indicates the time, in milliseconds, between timer ticks.
///
[
SRCategory(SR.CatBehavior),
DefaultValue(100),
SRDescription(SR.TimerIntervalDescr)
]
public int Interval {
get {
return interval;
}
set {
lock(syncObj) {
if (value < 1)
throw new ArgumentOutOfRangeException("Interval", SR.GetString(SR.TimerInvalidInterval, value, (0).ToString(CultureInfo.CurrentCulture)));
if (interval != value) {
interval = value;
if (Enabled) {
Debug.Assert(DesignMode || timerWindow != null, "Why don't we have a timer HWND?");
// just change the timer value, don't tear down the timer
// itself.
//
if (!DesignMode && timerWindow != null) {
timerWindow.RestartTimer(value);
}
}
}
}
}
}
///
///
/// Raises the
/// event.
///
protected virtual void OnTick(EventArgs e) {
if (onTimer != null) onTimer(this, e);
}
///
///
/// Starts the
/// timer.
///
public void Start() {
Enabled = true;
}
///
///
/// Stops the
/// timer.
///
public void Stop() {
Enabled = false;
}
///
///
/// returns us as a string.
///
///
public override string ToString() {
string s = base.ToString();
return s + ", Interval: " + Interval.ToString(CultureInfo.CurrentCulture);
}
private class TimerNativeWindow : NativeWindow {
// the timer that owns us
//
private Timer _owner;
// our current id -- this is usally the same as TimerID but we also
// use it as a flag of when our timer is running.
//
private int _timerID;
// arbitrary timer ID.
//
private static int TimerID = 1;
// setting this when we are stopping the timer so someone can't restart it in the process.
//
private bool _stoppingTimer;
internal TimerNativeWindow(Timer owner) {
this._owner = owner;
}
~TimerNativeWindow() {
// note this call will work form the finalizer thread.
//
StopTimer();
}
public bool IsTimerRunning {
get {
return _timerID != 0 && Handle != IntPtr.Zero;
}
}
// Ensures that our HWND has been created.
//
private bool EnsureHandle() {
if (Handle == IntPtr.Zero) {
// we create a totally vanilla invisible window just for WM_TIMER messages.
//
CreateParams cp = new CreateParams();
cp.Style = 0;
cp.ExStyle = 0;
cp.ClassStyle = 0;
cp.Caption = GetType().Name;
// Message only windows are cheaper and have fewer issues than
// full blown invisible windows. But, they are only supported
// on NT.
if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
cp.Parent = (IntPtr)NativeMethods.HWND_MESSAGE;
}
CreateHandle(cp);
}
Debug.Assert(Handle != IntPtr.Zero, "Timer HWND creation failed!");
return Handle != IntPtr.Zero;
}
// Returns true if we need to marshal across threads to access this timer's HWND.
//
private bool GetInvokeRequired(IntPtr hWnd) {
if (hWnd != IntPtr.Zero) {
int pid;
int hwndThread = SafeNativeMethods.GetWindowThreadProcessId(new HandleRef(this, hWnd), out pid);
int currentThread = SafeNativeMethods.GetCurrentThreadId();
return(hwndThread != currentThread);
}
return false;
}
// change the interval of the timer without destroying the HWND.
//
public void RestartTimer(int newInterval) {
StopTimer(false, IntPtr.Zero);
StartTimer(newInterval);
}
// Start the timer with the specified interval.
//
public void StartTimer(int interval) {
if (_timerID == 0 && !_stoppingTimer) {
if (EnsureHandle()) {
_timerID = (int) SafeNativeMethods.SetTimer(new HandleRef(this, Handle), TimerID++, interval, IntPtr.Zero);
}
}
}
// stop the timer.
//
public void StopTimer() {
StopTimer(true, IntPtr.Zero);
}
// stop the timer and optionally destroy the HWND.
//
public void StopTimer(bool destroyHwnd, IntPtr hWnd) {
if (hWnd == IntPtr.Zero) {
hWnd = Handle;
}
// Fire a message across threads to destroy the timer and HWND on the thread that created it.
//
if (GetInvokeRequired(hWnd)) {
UnsafeNativeMethods.PostMessage(new HandleRef(this, hWnd), NativeMethods.WM_CLOSE, 0, 0);
return;
}
// Locking 'this' here is ok since this is an internal class. See VSW#464499.
lock(this) {
if (_stoppingTimer || hWnd == IntPtr.Zero || !UnsafeNativeMethods.IsWindow(new HandleRef(this, hWnd))) {
return;
}
if (_timerID != 0) {
try {
_stoppingTimer = true;
SafeNativeMethods.KillTimer(new HandleRef(this, hWnd), _timerID);
}
finally {
_timerID = 0;
_stoppingTimer = false;
}
}
if (destroyHwnd) {
base.DestroyHandle();
}
}
}
// Destroy the handle, stopping the timer first.
//
public override void DestroyHandle() {
// don't recurse!
//
StopTimer(false, IntPtr.Zero);
Debug.Assert(_timerID == 0, "Destroying handle with timerID still set.");
base.DestroyHandle();
}
protected override void OnThreadException(Exception e) {
Application.OnThreadException(e);
}
public override void ReleaseHandle() {
// don't recurse!
//
StopTimer(false, IntPtr.Zero);
Debug.Assert(_timerID == 0, "Destroying handle with timerID still set.");
base.ReleaseHandle();
}
protected override void WndProc(ref Message m) {
Debug.Assert(m.HWnd == Handle && Handle != IntPtr.Zero, "Timer getting messages for other windows?");
// for timer messages, make sure they're ours (it'll be wierd if they aren't)
// and call the timer event.
//
if (m.Msg == NativeMethods.WM_TIMER) {
//Debug.Assert((int)m.WParam == _timerID, "Why are we getting a timer message that isn't ours?");
if ((int)m.WParam == _timerID) {
_owner.OnTick(EventArgs.Empty);
return;
}
}
else if (m.Msg == NativeMethods.WM_CLOSE) {
// this is a posted method from another thread that tells us we need
// to kill the timer. The handle may already be gone, so we specify it here.
//
StopTimer(true, m.HWnd);
return;
}
base.WndProc(ref m);
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
/*
*/
namespace System.Windows.Forms {
using System.Threading;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Diagnostics;
using System.Windows.Forms.Design;
using System;
using System.Globalization;
///
///
/// Implements a Windows-based timer that raises an event at user-defined intervals. This timer is optimized for
/// use in Win Forms
/// applications and must be used in a window.
///
[
DefaultProperty("Interval"),
DefaultEvent("Tick"),
ToolboxItemFilter("System.Windows.Forms"),
SRDescription(SR.DescriptionTimer)
]
public class Timer : Component {
///
///
///
private int interval;
///
///
///
private bool enabled;
///
///
///
private EventHandler onTimer;
///
///
///
private GCHandle timerRoot;
// our holder for the HWND that handles our Timer messages.
//
private TimerNativeWindow timerWindow;
///
///
///
private object userData;
private object syncObj = new object();
///
///
/// Initializes a new instance of the
/// class.
///
public Timer()
: base() {
interval = 100;
}
///
///
/// Initializes a new instance of the class with the specified container.
///
public Timer(IContainer container) : this() {
container.Add(this);
}
///
[
SRCategory(SR.CatData),
Localizable(false),
Bindable(true),
SRDescription(SR.ControlTagDescr),
DefaultValue(null),
TypeConverter(typeof(StringConverter)),
]
public object Tag {
get {
return userData;
}
set {
userData = value;
}
}
///
///
/// Occurs when the specified timer
/// interval has elapsed and the timer is enabled.
///
[SRCategory(SR.CatBehavior), SRDescription(SR.TimerTimerDescr)]
public event EventHandler Tick {
add {
onTimer += value;
}
remove {
onTimer -= value;
}
}
///
///
///
/// Disposes of the resources (other than memory) used by the timer.
///
///
protected override void Dispose(bool disposing) {
if (disposing) {
if (timerWindow != null) {
timerWindow.StopTimer();
}
Enabled = false;
}
timerWindow = null;
base.Dispose(disposing);
}
///
///
/// Indicates whether the timer is
/// running.
///
[
SRCategory(SR.CatBehavior),
DefaultValue(false),
SRDescription(SR.TimerEnabledDescr)
]
public virtual bool Enabled {
get {
if (timerWindow == null) {
return enabled;
}
return timerWindow.IsTimerRunning;
}
set {
lock(syncObj) {
if (enabled != value) {
enabled = value;
// At runtime, enable or disable the corresponding Windows timer
//
if (!DesignMode) {
if (value) {
// create the timer window if needed.
//
if (timerWindow == null) {
timerWindow = new TimerNativeWindow(this);
}
timerRoot = GCHandle.Alloc(this);
timerWindow.StartTimer(interval);
}
else{
if (timerWindow != null){
timerWindow.StopTimer();
}
if (timerRoot.IsAllocated) {
timerRoot.Free();
}
}
}
}
}
}
}
///
///
///
/// Indicates the time, in milliseconds, between timer ticks.
///
[
SRCategory(SR.CatBehavior),
DefaultValue(100),
SRDescription(SR.TimerIntervalDescr)
]
public int Interval {
get {
return interval;
}
set {
lock(syncObj) {
if (value < 1)
throw new ArgumentOutOfRangeException("Interval", SR.GetString(SR.TimerInvalidInterval, value, (0).ToString(CultureInfo.CurrentCulture)));
if (interval != value) {
interval = value;
if (Enabled) {
Debug.Assert(DesignMode || timerWindow != null, "Why don't we have a timer HWND?");
// just change the timer value, don't tear down the timer
// itself.
//
if (!DesignMode && timerWindow != null) {
timerWindow.RestartTimer(value);
}
}
}
}
}
}
///
///
/// Raises the
/// event.
///
protected virtual void OnTick(EventArgs e) {
if (onTimer != null) onTimer(this, e);
}
///
///
/// Starts the
/// timer.
///
public void Start() {
Enabled = true;
}
///
///
/// Stops the
/// timer.
///
public void Stop() {
Enabled = false;
}
///
///
/// returns us as a string.
///
///
public override string ToString() {
string s = base.ToString();
return s + ", Interval: " + Interval.ToString(CultureInfo.CurrentCulture);
}
private class TimerNativeWindow : NativeWindow {
// the timer that owns us
//
private Timer _owner;
// our current id -- this is usally the same as TimerID but we also
// use it as a flag of when our timer is running.
//
private int _timerID;
// arbitrary timer ID.
//
private static int TimerID = 1;
// setting this when we are stopping the timer so someone can't restart it in the process.
//
private bool _stoppingTimer;
internal TimerNativeWindow(Timer owner) {
this._owner = owner;
}
~TimerNativeWindow() {
// note this call will work form the finalizer thread.
//
StopTimer();
}
public bool IsTimerRunning {
get {
return _timerID != 0 && Handle != IntPtr.Zero;
}
}
// Ensures that our HWND has been created.
//
private bool EnsureHandle() {
if (Handle == IntPtr.Zero) {
// we create a totally vanilla invisible window just for WM_TIMER messages.
//
CreateParams cp = new CreateParams();
cp.Style = 0;
cp.ExStyle = 0;
cp.ClassStyle = 0;
cp.Caption = GetType().Name;
// Message only windows are cheaper and have fewer issues than
// full blown invisible windows. But, they are only supported
// on NT.
if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
cp.Parent = (IntPtr)NativeMethods.HWND_MESSAGE;
}
CreateHandle(cp);
}
Debug.Assert(Handle != IntPtr.Zero, "Timer HWND creation failed!");
return Handle != IntPtr.Zero;
}
// Returns true if we need to marshal across threads to access this timer's HWND.
//
private bool GetInvokeRequired(IntPtr hWnd) {
if (hWnd != IntPtr.Zero) {
int pid;
int hwndThread = SafeNativeMethods.GetWindowThreadProcessId(new HandleRef(this, hWnd), out pid);
int currentThread = SafeNativeMethods.GetCurrentThreadId();
return(hwndThread != currentThread);
}
return false;
}
// change the interval of the timer without destroying the HWND.
//
public void RestartTimer(int newInterval) {
StopTimer(false, IntPtr.Zero);
StartTimer(newInterval);
}
// Start the timer with the specified interval.
//
public void StartTimer(int interval) {
if (_timerID == 0 && !_stoppingTimer) {
if (EnsureHandle()) {
_timerID = (int) SafeNativeMethods.SetTimer(new HandleRef(this, Handle), TimerID++, interval, IntPtr.Zero);
}
}
}
// stop the timer.
//
public void StopTimer() {
StopTimer(true, IntPtr.Zero);
}
// stop the timer and optionally destroy the HWND.
//
public void StopTimer(bool destroyHwnd, IntPtr hWnd) {
if (hWnd == IntPtr.Zero) {
hWnd = Handle;
}
// Fire a message across threads to destroy the timer and HWND on the thread that created it.
//
if (GetInvokeRequired(hWnd)) {
UnsafeNativeMethods.PostMessage(new HandleRef(this, hWnd), NativeMethods.WM_CLOSE, 0, 0);
return;
}
// Locking 'this' here is ok since this is an internal class. See VSW#464499.
lock(this) {
if (_stoppingTimer || hWnd == IntPtr.Zero || !UnsafeNativeMethods.IsWindow(new HandleRef(this, hWnd))) {
return;
}
if (_timerID != 0) {
try {
_stoppingTimer = true;
SafeNativeMethods.KillTimer(new HandleRef(this, hWnd), _timerID);
}
finally {
_timerID = 0;
_stoppingTimer = false;
}
}
if (destroyHwnd) {
base.DestroyHandle();
}
}
}
// Destroy the handle, stopping the timer first.
//
public override void DestroyHandle() {
// don't recurse!
//
StopTimer(false, IntPtr.Zero);
Debug.Assert(_timerID == 0, "Destroying handle with timerID still set.");
base.DestroyHandle();
}
protected override void OnThreadException(Exception e) {
Application.OnThreadException(e);
}
public override void ReleaseHandle() {
// don't recurse!
//
StopTimer(false, IntPtr.Zero);
Debug.Assert(_timerID == 0, "Destroying handle with timerID still set.");
base.ReleaseHandle();
}
protected override void WndProc(ref Message m) {
Debug.Assert(m.HWnd == Handle && Handle != IntPtr.Zero, "Timer getting messages for other windows?");
// for timer messages, make sure they're ours (it'll be wierd if they aren't)
// and call the timer event.
//
if (m.Msg == NativeMethods.WM_TIMER) {
//Debug.Assert((int)m.WParam == _timerID, "Why are we getting a timer message that isn't ours?");
if ((int)m.WParam == _timerID) {
_owner.OnTick(EventArgs.Empty);
return;
}
}
else if (m.Msg == NativeMethods.WM_CLOSE) {
// this is a posted method from another thread that tells us we need
// to kill the timer. The handle may already be gone, so we specify it here.
//
StopTimer(true, m.HWnd);
return;
}
base.WndProc(ref m);
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- NegotiationTokenAuthenticatorStateCache.cs
- SplineKeyFrames.cs
- CmsInterop.cs
- CollectionEditVerbManager.cs
- ReferentialConstraint.cs
- OracleTimeSpan.cs
- WebPartExportVerb.cs
- AuthenticatingEventArgs.cs
- CookieParameter.cs
- WmlMobileTextWriter.cs
- Dynamic.cs
- Trace.cs
- ExpressionList.cs
- GridItemCollection.cs
- AddingNewEventArgs.cs
- RelationshipConverter.cs
- HandlerBase.cs
- HtmlPanelAdapter.cs
- DbCommandDefinition.cs
- FormViewInsertedEventArgs.cs
- HybridDictionary.cs
- ColorContextHelper.cs
- SerializerProvider.cs
- ArithmeticException.cs
- FontClient.cs
- EntityReference.cs
- RowUpdatingEventArgs.cs
- IdentifierCollection.cs
- ZipFileInfoCollection.cs
- TypeGeneratedEventArgs.cs
- exports.cs
- HealthMonitoringSectionHelper.cs
- Icon.cs
- SchemaCollectionCompiler.cs
- ProfileModule.cs
- HtmlContainerControl.cs
- SelectingProviderEventArgs.cs
- UnicodeEncoding.cs
- BindingMAnagerBase.cs
- SerializationException.cs
- unitconverter.cs
- TokenBasedSetEnumerator.cs
- ReadContentAsBinaryHelper.cs
- ModelFunction.cs
- PropertyGridEditorPart.cs
- ReturnValue.cs
- DefaultTextStore.cs
- typedescriptorpermissionattribute.cs
- SecurityIdentifierElementCollection.cs
- ErrorTolerantObjectWriter.cs
- EntityDataSourceChangingEventArgs.cs
- BamlBinaryReader.cs
- NativeMethods.cs
- PasswordTextNavigator.cs
- SqlConnectionString.cs
- FlowDocumentScrollViewer.cs
- XPathAncestorIterator.cs
- XmlSchemaObjectTable.cs
- StreamWithDictionary.cs
- PanelStyle.cs
- ExportException.cs
- TdsParserSafeHandles.cs
- BaseValidator.cs
- HtmlElementCollection.cs
- ConstructorExpr.cs
- SiteMapProvider.cs
- EmissiveMaterial.cs
- Exception.cs
- SystemIPInterfaceProperties.cs
- DynamicContractTypeBuilder.cs
- TransformerConfigurationWizardBase.cs
- HttpCookieCollection.cs
- SchemaTypeEmitter.cs
- NamedPermissionSet.cs
- QilUnary.cs
- WindowPatternIdentifiers.cs
- ObjectToken.cs
- SqlFacetAttribute.cs
- SqlBuilder.cs
- OleDbSchemaGuid.cs
- IListConverters.cs
- ContainerCodeDomSerializer.cs
- CookieProtection.cs
- LassoSelectionBehavior.cs
- WebPartTransformerAttribute.cs
- NativeCompoundFileAPIs.cs
- HTMLTextWriter.cs
- DataKey.cs
- GeometryValueSerializer.cs
- WebPartTransformer.cs
- RIPEMD160.cs
- ProviderIncompatibleException.cs
- AttributeCollection.cs
- InputLangChangeRequestEvent.cs
- DateTimeFormat.cs
- WebPartConnectVerb.cs
- ScriptControlDescriptor.cs
- _RequestCacheProtocol.cs
- UriTemplateEquivalenceComparer.cs
- RichTextBoxAutomationPeer.cs