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
- MailBnfHelper.cs
- Lasso.cs
- MenuItem.cs
- SqlErrorCollection.cs
- XmlToDatasetMap.cs
- ToolStripPanelCell.cs
- CustomError.cs
- ObjectToken.cs
- InvalidDataException.cs
- Image.cs
- Table.cs
- DataErrorValidationRule.cs
- ColorMatrix.cs
- RuleSetBrowserDialog.cs
- TerminateWorkflow.cs
- PreviousTrackingServiceAttribute.cs
- DataTableMappingCollection.cs
- NetworkInformationPermission.cs
- SiteMapSection.cs
- DoubleSumAggregationOperator.cs
- WebPartEditorCancelVerb.cs
- HasCopySemanticsAttribute.cs
- FlowchartDesigner.xaml.cs
- Grid.cs
- System.Data.OracleClient_BID.cs
- DesignerAttribute.cs
- AQNBuilder.cs
- WebControlToolBoxItem.cs
- CheckableControlBaseAdapter.cs
- BackgroundFormatInfo.cs
- HandleCollector.cs
- TextPatternIdentifiers.cs
- Line.cs
- XmlObjectSerializerReadContextComplex.cs
- EntityDesignerUtils.cs
- FontStyleConverter.cs
- ValuePattern.cs
- EmbeddedMailObject.cs
- DatagridviewDisplayedBandsData.cs
- TextTreeRootTextBlock.cs
- WebBrowserEvent.cs
- TerminatorSinks.cs
- DesignBindingPropertyDescriptor.cs
- SqlDataSourceView.cs
- DbProviderManifest.cs
- ObjectConverter.cs
- SymmetricKeyWrap.cs
- WindowsListViewGroup.cs
- GridViewDeletedEventArgs.cs
- dataprotectionpermission.cs
- TextCompositionEventArgs.cs
- SingleResultAttribute.cs
- MulticastOption.cs
- SqlNodeAnnotation.cs
- DataControlFieldCell.cs
- Utils.cs
- UInt16Converter.cs
- ColorConvertedBitmap.cs
- MinimizableAttributeTypeConverter.cs
- PermissionAttributes.cs
- NumberAction.cs
- IApplicationTrustManager.cs
- PauseStoryboard.cs
- SystemGatewayIPAddressInformation.cs
- WebPartAuthorizationEventArgs.cs
- SupportsEventValidationAttribute.cs
- ServiceReference.cs
- InputBinding.cs
- _ScatterGatherBuffers.cs
- ApplicationHost.cs
- ColumnClickEvent.cs
- StringPropertyBuilder.cs
- RegexNode.cs
- AssemblyName.cs
- ControlDesigner.cs
- ShaperBuffers.cs
- FillBehavior.cs
- BamlCollectionHolder.cs
- TypeGeneratedEventArgs.cs
- ExceptionHelpers.cs
- TraversalRequest.cs
- ResourceKey.cs
- VirtualizingPanel.cs
- SoapTypeAttribute.cs
- DescendentsWalker.cs
- SiteMapPath.cs
- MLangCodePageEncoding.cs
- AncestorChangedEventArgs.cs
- ClassDataContract.cs
- TdsValueSetter.cs
- ScriptingSectionGroup.cs
- SpeechSeg.cs
- IdentityElement.cs
- EnumerableCollectionView.cs
- DataGridCellsPanel.cs
- Symbol.cs
- Setter.cs
- ValidationRuleCollection.cs
- OneWayChannelFactory.cs
- PocoPropertyAccessorStrategy.cs