Where are your favorite Windows APIs in the .NET Framework? This article points out where the Windows Sleep() function now can be found.
- Download source — 43.7 KB
Figure 1. The Sleep.NET Main Window |
Figure 2. User feedback while sleeping |
Introduction
I am just starting out with Windows Forms and .NET programming in general and I am learning my trade all over again. My background is as a C++/Win32 GUI and DCOM programmer with a strong MFC and Win32 Functions emphasis.
I relented and now do Windows Forms and ASP.NET programming, and I have discovered how effortless .NET development is when using Microsoft’s excellent tool, Visual Studio 2005 and up. Truth is, I am never going back. My personal preference is to use .NET and the visual tools provided by Microsoft to do my development from now on. Unmanaged C/C++ and MFC is not worth the extra time I see myself spending using those languages.
About This Series
However, now that I am coming to my trade all over again in some sense, I am having to learn where my old familiar Windows API functions are in the .NET world. I am sure I am not alone as there are other .NET beginners out there.
Audience
This series, «The ____ in .NET,» is something I am going to publish on The Code Project from time to time in an effort to provide beginners and newbies with quick, piecemeal tutorials on your favorite functionality. This is not a re-hash of the VS «How Do I?…» docs, since they provide more comprehensive help. These are «tutorials to go,» that focus very narrowly on one or other individual functionality items.
Language Used
Because my employer is having me do things in C#, the sample code provided with the articles in this series will all be in C#. I take it Visual Basic, etc., developers are smart, intelligent, capable people who can translate between languages as necessary.
Background
In Windows, APIs are provided to suspend threads and processes for a programmer-specified time period, usually given in milleseconds. In the old, Visual Studio-6.0-and-below-esque, unmanaged C++ and MFC, one could suspend the current thread (i.e., make your window stop responding) as such:
void CMyDialog::OnClickedSleep() { ::Sleep(500); }
Listing 1. A MFC message handler calling the Win32 function, ::Sleep()
Question is, where does this Sleep()
function sit in the new .NET Framework?
To suspend an application, you must call the
System.Threading.Thread.Sleep()
static method. It takes one parameter, anint
specifying the delay, in milliseconds.
This concludes this article. If you are a beginner and want help implementing this in your application, I invite you to follow the tutorial below to build the sample application distributed with this article.
Tutorial: Sleep.NET
This article presents a small sample Windows Forms application, Sleep.NET
, demonstrating the use of the System.Threading.Thread.Sleep()
static method.
Step 1: Open your copy of Visual Studio.NET
Step 2: Click the File menu, point to New, and then click Project
- Visual Studio opens the New Project window.
Step 3: In the Project Types box on the left, click Visual C#, and then click Windows
- If it is your personal preference, you may also choose your .NET language of choice to implement this tutorial in. It must be Windows Forms-compatible.
Step 4: In the Templates box on the right, under Visual Studio installed templates, click Windows Application
Step 5: In the Name box, type Sleep.NET
- You may use whichever name you choose if you’re following along; here, we shall use
Sleep.NET.
Step 6: Using the Visual Studio Forms Designer — which I am going to leave the use of for you to learn — create a main form to match Figure 1 above.
- In my form, the Sleep for: text box was given the
Name
propertytxtSleep
- I assigned the value
btnSleep
for the Sleep button’sName
property - I assigned the value
btnQuit
for the Quit button’s Name property - I set the form’s
AcceptButton
property tobtnSleep
and the form’sCancelButton
property I set to have the valuebtnQuit
Step 7: Once your form has been created, press CTRL+F5 to build and run the project, so as to test. In order to kill the app, you will have to press the ALT+F4 keys on your keyboard.
Step 8: Purely for aesthetics, we’re going to program the form window to center itself on the screen before it’s shown. Double-click anywhere in a blank area of the form.
- The code window opens, with the insertion point on the
Form1_Load
event handler - For help on this event handler, lookup
Form.Load (Windows Forms)
in the docs
Step 9: Implement the Form1_Load
event handler as follows:
private void Form1_Load(object sender, EventArgs e) { CenterToScreen(); Show(); titleOld = this.Text; }
- This listing saves the window’s default title — since we update the title when we’re sleeping to indicate so to the user, shown below.
Step 10: Add a field to the Form1
class to store the window’s default title. Open the Form1.cs file and add the code shown below:
namespace Sleep.NET { public partial class Form1 : Form { String titleOld; ... } }
Step 11: Double-click the Quit button in the Designer, which brings you to code for the btnQuit_Click
event handler. Implement the handler as shown below:
private void btnQuit_Click(object sender, EventArgs e) { Hide(); Application.Exit(); }
Step 12: Double-click the Sleep button in the Designer, and add the following code:
private void btnSleep_Click(object sender, EventArgs e) { EnableUI(false); Int32 SleepTime = 0; if (Int32.TryParse(txtSleep.Text, out SleepTime)) { System.Threading.Thread.Sleep(SleepTime); } EnableUI(true;) }
Step 13: Add the EnableUI()
method to the Form1
class, implemented as shown below.
- This method enables/disables the text box specifying the time to sleep for, enables/disables the Sleep button, and updates the form’s title to reflect its status.
private void EnableUI() { txtSleep.Enabled = Enabled; this.Text = Enabled ? titleOld : "Sleep.NET - Sleeping"; btnSleep.Enabled = Enabled; Refresh(); }
Step 14: Press CTRL+S on your keyboard to save your changes, and then CTRL+F5 in order to build and test the sample code.
- To test the sample code, enter a number of milliseconds (1 second = 1000 milliseconds) in the Sleep for: box, and then click Sleep. The title bar changes to say
Sleeping
, and the text box is grayed out for the duration of the sleep - Experiment and try some other lengths of time and see the resulting behavior.
- When finished, close the sample application by clicking Quit or pressing ESC.
Points of Interest
In this section, we shall review interesting facts and .NET features learned while implementing the sample. Among these are:
- Message-pumping — in order to update the user-interface (UI) — with
Control.Refresh()
- You can also refresh the form by calling its
Refresh()
method - Using
Refresh()
is more thread-safe than, e.g.,Application.DoEvents()
- Converting a
String
value to a 32-bitint
value (to pass to theSleep
function) withInt32.TryParse()
I want to take a moment and acknowledge message board posters dubbele onzin and norm .net below for their comments about avoiding the use of Application.DoEvents()
in favor of Refresh()
.
Refresh()
Notice the setting of properties of controls to, say, enable or disable them, or change the text. Note that when using Sleep()
, the application’s Windows messages must be pumped (i.e., collected and distributed to all message handlers) or else the controls will not visibly change their state.
In the days of yore, or for those unlucky enough to still be maintaining legacy Win32 code, the way to pump messages is to run a message loop:
void MessageLoop() { MSG msg; while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } }
Listing 2. A legacy Win32 message pump
or some variant thereof, as appropriate to one’s application. With .NET, things are simpler, and in particular only one line of code accomplishes the same. Note that the function shown below can be called either for the whole form, or the control whose UI you want to refresh. This is shown in ‘Listing 3’ below:
Refresh();
Listing 3. A message pump run in .NET (C#)
Whenever you change a UI-visible property of a control, such as Enabled
, you want to make sure and force the UI to update with a call to Control.Refresh()
before you implement other functionality.
Int32.TryParse()
The int
type — as well as the other types — appears to implement the TryParse()
method, which takes as parameters a string
and an out
parameter which is the type into which to convert the string
. The useful aspect of this method is that it returns false
if there is garbage in the string
and you can simply avoid processing the result if this occurs, as is shown in ‘Listing 1’.
Int32.TryParse(string s, out Int32 result)
Notice how an out
parameter is used. You first declare an instance of the variable to which the parsed value should be assigned. Next, supply the variable to the out
parameter, with the out
keyword in front of the variable name. Finally, test the method’s return
value for true
before using the result.
Where To Go for Help
Feel free to email me with specific questions about this article, and I will be happy to explain. I also want to invite you to make use of the Forums at the bottom of this article. I wish you well.
History
In this section, I will keep a running history of the changes and updates I’ve made to this article.
- 16 Oct 2007 9:08 AM Pacific
Article updated to reflect the use ofRefresh()
in lieu ofApplication.DoEvents()
to update the UI, and the use ofInt32.TryParse()
in lieu ofConvert.ToInt32()
as per reader feedback and tips (see below) - 11 Oct 2007 12:46 PM Pacific
Article written
Как использовать OAuth2 со Spring Security в Java
Javaican 14.05.2025
Протокол OAuth2 часто путают с механизмами аутентификации, хотя по сути это протокол авторизации. Представьте, что вместо передачи ключей от всего дома вашему другу, который пришёл полить цветы, вы. . .
Анализ текста на Python с NLTK и Spacy
AI_Generated 14.05.2025
NLTK, старожил в мире обработки естественного языка на Python, содержит богатейшую коллекцию алгоритмов и готовых моделей. Эта библиотека отлично подходит для образовательных целей и. . .
Реализация DI в PHP
Jason-Webb 13.05.2025
Когда я начинал писать свой первый крупный PHP-проект, моя архитектура напоминала запутаный клубок спагетти. Классы создавали другие классы внутри себя, зависимости жостко прописывались в коде, а о. . .
Обработка изображений в реальном времени на C# с OpenCV
stackOverflow 13.05.2025
Объединение библиотеки компьютерного зрения OpenCV с современным языком программирования C# создаёт симбиоз, который открывает доступ к впечатляющему набору возможностей. Ключевое преимущество этого. . .
POCO, ACE, Loki и другие продвинутые C++ библиотеки
NullReferenced 13.05.2025
В C++ разработки существует такое обилие библиотек, что порой кажется, будто ты заблудился в дремучем лесу. И среди этого многообразия POCO (Portable Components) – как маяк для тех, кто ищет. . .
Паттерны проектирования GoF на C#
UnmanagedCoder 13.05.2025
Вы наверняка сталкивались с ситуациями, когда код разрастается до неприличных размеров, а его поддержка становится настоящим испытанием. Именно в такие моменты на помощь приходят паттерны Gang of. . .
Создаем CLI приложение на Python с Prompt Toolkit
py-thonny 13.05.2025
Современные командные интерфейсы давно перестали быть черно-белыми текстовыми программами, которые многие помнят по старым операционным системам. CLI сегодня – это мощные, интуитивные и даже. . .
Конвейеры ETL с Apache Airflow и Python
AI_Generated 13.05.2025
ETL-конвейеры – это набор процессов, отвечающих за извлечение данных из различных источников (Extract), их преобразование в нужный формат (Transform) и загрузку в целевое хранилище (Load). . . .
Выполнение асинхронных задач в Python с asyncio
py-thonny 12.05.2025
Современный мир программирования похож на оживлённый мегаполис – тысячи процессов одновременно требуют внимания, ресурсов и времени. В этих джунглях операций возникают ситуации, когда программа. . .
Работа с gRPC сервисами на C#
UnmanagedCoder 12.05.2025
gRPC (Google Remote Procedure Call) — открытый высокопроизводительный RPC-фреймворк, изначально разработанный компанией Google. Он отличается от традиционых REST-сервисов как минимум тем, что. . .
Last Updated :
01 Feb, 2019
In C#, a Sleep() method temporarily suspends the current execution of the thread for specified milliseconds, so that other threads can get the chance to start the execution, or may get the CPU for execution. There are two methods in the overload list of Thread.Sleep
Method as follows:
- Sleep(Int32)
- Sleep(TimeSpan)
Sleep(Int32)
This method suspends the current thread for the descriptor number of milliseconds. This method will throw an ArgumentOutOfRangeException if the time-out value is negative and is not equal to infinite.
Syntax:
public static void Sleep (int millisecondsTimeout);
Here, millisecondsTimeout is a number of milliseconds for which the thread is suspended. If the value of the millisecondsTimeout argument is zero, then the thread renounces the remainder of its time slice to any thread of equal priority that is ready to run. If there are no other threads of equal priority that are ready to run, then execution of the current thread is not suspended.
Example:
CSharp
// C# program to illustrate the // concept of Sleep(Int32) method using System; using System.Threading; class ExampleofThread { // Non-Static method public void thread1() { for (int x = 0; x < 2; x++) { Console.WriteLine("Thread1 is working"); // Sleep for 4 seconds // Using Sleep() method Thread.Sleep(4000); } } // Non-Static method public void thread2() { for (int x = 0; x < 2; x++) { Console.WriteLine("Thread2 is working"); } } } // Driver Class public class ThreadExample { // Main method public static void Main() { // Creating instance for mythread() method ExampleofThread obj = new ExampleofThread(); // Creating and initializing threads Thread thr1 = new Thread(new ThreadStart(obj.thread1)); Thread thr2 = new Thread(new ThreadStart(obj.thread2)); thr1.Start(); thr2.Start(); } }
Output:
Thread1 is working Thread2 is working Thread2 is working Thread1 is working
Explanation: By using Thread.Sleep(4000);
in the thread1 method, we make the thr1 thread sleep for 4 seconds, so in between 4 seconds the thr2 thread gets the chance to execute after 4 seconds the thr1 thread resume its working.
Sleep(TimeSpan)
This method suspends the current thread for the described amount of time. This method will throw an ArgumentOutOfRangeException if the value of timeout is negative and is not equal to the infinite in milliseconds, or is greater than MaxValue milliseconds.
Syntax :
public static void Sleep (TimeSpan timeout);
Here, the timeout is the amount of time for which the thread is suspended. If the value of the millisecondsTimeout argument is Zero, then the thread renounces the remainder of its time slice to any thread of equal priority that is ready to run. If there are no other threads of equal priority that are ready to run, then execution of the current thread is not suspended.
Example:
CSharp
// C# program to illustrate the // concept of Sleep(TimeSpan) using System; using System.Threading; class GFG { // Main method static void Main() { // Set the timeout value, i.e. 3 seconds TimeSpan timeout = new TimeSpan(0, 0, 3); for (int k = 0; k < 3; k++) { Console.WriteLine("Thread is" + " sleeping for 3 seconds."); // Using Sleep(TimeSpan) method Thread.Sleep(timeout); } Console.WriteLine("Main thread exits"); } }
Output:
Thread is sleeping for 3 seconds. Thread is sleeping for 3 seconds. Thread is sleeping for 3 seconds. Main thread exits
Reference:
- https://docs.microsoft.com/en-us/dotnet/api/system.threading.thread.sleep?view=netframework-4.7.2
Introduction
When programming, it is common to want to pause execution for a certain amount of time and most common programming and scripting languages have some form of Sleep command built in to achieve this.
For example, when we’ve encountered a problem with a remote resource, it’s common to back-off (pause execution) for a short amount of time and retry.
Here I’ll go through the various options for introducing a delay in C#, ranging from the most basic (Thread.Sleep()) – suitable for use in a single threaded console application. To more complicated versions for use in multi threaded interactive applications.
Add a delay in C# using Thread.Sleep()
// Will delay for three seconds Thread.Sleep(3000);
Using Thread.Sleep() is the simplest way to introduce a delay in C# code, but it will hang the main thread for the duration of the delay, so it’s only really appropriate for console applications. Assuming you’re happy with that, let’s dive into a more complete example:
using System; using System.Threading; class Program { static void Main() { Console.WriteLine($"Delay starting at {DateTime.Now}"); // Will delay for three seconds var milliseconds = 3000; Thread.Sleep(milliseconds); Console.WriteLine($"Finished delay at {DateTime.Now}"); } } /* this code outputs: Delay starting at 13/11/2020 11:59:39 Finished delay at 13/11/2020 11:59:42 */
A common mistake when first using Thread.Sleep() is to forget the using, result in the following error:
error CS0103 C# The name 'Thread' does not exist in the current context
This is easily fixed by adding a “using System.Threading;” line at the top of the file, as in the above example.
The next thing to note is that Thread.Sleep() takes miliseconds as it’s argument, so if you want to sleep for 3 seconds you need to pass the number 3000. It’s possible to make your intent clearer using a timespan like this:
Thread.Sleep(TimeSpan.FromSeconds(3));
But older versions of Thread.Sleep didn’t take a TimeSpan, so your mileage may vary.
Add a Delay in C# without blocking main thread using Task.Delay()
// Will delay for 3 seconds await Task.Delay(3000);
There is an asynchronous version of Thread.Sleep called Task.Delay. If you’re not familiar with how asynchronous calls work in C# then I’m planning a series of posts on the topic (let me know you want it in the comments!). Until that’s up, see the official docs if you need more info.
The idea here is to start a new task that runs the delay in the background, let’s look at an example:
using System; using System.Threading.Tasks; class Program { async static Task Main() { Console.WriteLine($"Delay starting at {DateTime.Now}"); // Will delay for 3 seconds await Task.Delay(3000); Console.WriteLine($"Finished delay at {DateTime.Now}"); } } /* this code outputs: Delay starting at 13/11/2020 12:23:09 Finished delay at 13/11/2020 12:23:12 */
Once again if you forget the using, you might encounter the following error:
CS0246 C# The type or namespace name 'Task' could not be found (are you missing a using directive or an assembly reference?)
Be sure to add “using System.Threading.Tasks;” to avoid this.
Note also that we’ve had to make our main method async and return a Task rather than void. This is a contrived example, and if you’ve got a console application as simple of this one there’s no need for this asynchronous version (just use sleep). Forgetting to do that can result in this error:
CS4033 C# The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.
So what can we do with this asynchronous delay that can’t be done with the basic Thread.Sleep()? Quite simply, we can get other things done while we wait for the delay to finish. Time for a further example:
using System; using System.Threading; using System.Threading.Tasks; class Program { static void Main() { Console.WriteLine($"Delay starting at {DateTime.Now}"); //Sleep for 3 seconds in the background var delay = Task.Delay(TimeSpan.FromSeconds(3)); var seconds = 0; while (!delay.IsCompleted) { // While we're waiting, note the time ticking past seconds++; Thread.Sleep(TimeSpan.FromSeconds(1)); Console.WriteLine($"Waiting... {seconds}"); } Console.WriteLine($"Finished delay at {DateTime.Now} after {seconds} seconds"); } } /* this code outputs: Delay starting at 13/11/2020 12:44:49 Waiting... 1 Waiting... 2 Waiting... 3 Finished delay at 13/11/2020 12:44:52 after 3 seconds */
This example makes use of the fact that Task.Delay() is running in the background, and allows the main thread to do some useful (or not!) work. In this example the main thread just outputs “Waiting… {seconds}”, but I’d argue that even that is useful as it provides feedback to the user that the console application is still actively working, it could easily be updated to print the % done or similar.
I hope I’ve not confused things by combining both Task.Delay() and Thread.Sleep() in one example!
For interactive (non-console) applications it’s especially important that the main thread can respond to inputs, allowing the program to remain interactive while delays are processed in the background.
Add a repeating delay in C# using one of the Timer classes
There are several timer classes that can be used to repeatedly trigger events after a certain period of time has elapsed:
System.Timers.Timer
System.Threading.Timer
System.Windows.Forms.Timer (.NET Framework only)
System.Web.UI.Timer
System.Windows.Threading.DispatcherTimer
Each of these timer classes has different functionality, with these remarks on MSDN giving more details of which to use depending on your requirements.
If you just want a single delay in C# then use either Thread.Sleep() or Task.Delay() as described above. However, if you’re after a repeating delay, a timer can be helpful.
For the purposes of the following examples, I’m going to use a System.Threading.Timer() as it appears to be Microsoft preferred general purpose timer.
The thrust of using a timer comes from instantiating a new System.Threading.Timer(), to which you need to supply at least three arguments: callback, dueTime and period.
- callback TimerCallback – this is the method that should be called whenever the timer fires
- dueTime int/Timespan – this is how long to wait before the timer first fires
- period int/TimeSpan – this is how long to wait between each subsequent firing of the timer
As example of such an instantiation might be:
var timer = new System.Threading.Timer( DoSomething, null, TimeSpan.FromSeconds(5), // time to first firing TimeSpan.FromSeconds(1)); // delay for each subsequent firing
This starts a timer that will wait 5 seconds before calling DoSomething, which it will continue to do once a second after that.
The following example is more complete, showing you how to set up the callback, one way of tracking the number of times it’s called, and how to signal that the timer should finish and then stop it. Here’re the code:
using System; using System.Threading; class Program { static void Main() { Console.WriteLine($"Delay starting at {DateTime.Now}"); var idleWaiter = new IdleWaiter(3); // Create an AutoResetEvent to signal when the IdleWaiter was reached it's limit var autoEvent = new AutoResetEvent(false); var timer = new System.Threading.Timer( idleWaiter.PrintWaiting, autoEvent, TimeSpan.FromSeconds(1), // time to first firing TimeSpan.FromSeconds(1)); // delay for each subsequent firing // Wait until the autoevent signals; autoEvent.WaitOne(); // Dispose of the timer timer.Dispose(); Console.WriteLine($"Finished delay at {DateTime.Now} after {idleWaiter.TimesCalled} seconds"); } } class IdleWaiter { public IdleWaiter(int threshold) { this.Threshold = threshold; } public int TimesCalled { get; private set; } public int Threshold { get; } public void PrintWaiting(object stateInfo) { var autoEvent = (AutoResetEvent)stateInfo; Console.WriteLine($"Waiting... {++this.TimesCalled}"); if (this.TimesCalled >= Threshold) { autoEvent.Set(); } } } /* this code outputs: Delay starting at 13/11/2020 13:44:39 Waiting... 1 Waiting... 2 Waiting... 3 Finished delay at 13/11/2020 13:44:42 after 3 seconds */
I know it’s a bit heavy, but in the above example I’ve created a new class IdleWaiter which is responsible for printing “Waiting…” each time it’s called, while tracking the number of times it’s been called and signalling (via an autoResetEvent) when it’s reached a threshold.
When you run this code, the timer fires every seconds until it’s been run three times, then it signals that it’s reached it’s threshold and we stop the timer by disposing of it.
If we didn’t dispose of the timer it would keep on ticking once every second. You can try this for yourself by commenting out the dispose line and adding a Thread.Sleep() to stop the program exiting:
// Dispose of the timer //timer.Dispose(); Console.WriteLine($"Finished delay at {DateTime.Now} after {idleWaiter.TimesCalled} seconds"); Thread.Sleep(5000);
If you run the above code with this change you get the following output:
Delay starting at 13/11/2020 13:56:32 Waiting... 1 Waiting... 2 Waiting... 3 Finished delay at 13/11/2020 13:56:35 after 3 seconds Waiting... 4 Waiting... 5 Waiting... 6 Waiting... 7 Waiting... 8
Using a Timer might be the right choice if you want a task to repeat on a schedule, but given the added complexity, I’d probably stick to the other options for most use cases.
Conclusion
If you’re in a console app, or some other single threaded application, you can use Thread.Sleep() to trigger a delay, just be careful with the fact this takes milliseconds (or better yet use TimeSpan.FromSeconds()).
If you want to delay in an asynchronous way, allowing your main thread to do useful work in the interim, Thread.Delay() is they way to go.
If you’re want to kick something off repeatedly with a delay in between, then you should be using a timer like System.threading.Timer.
I’m sure there are other ways of adding a delay in C#, but I think I’ve covered off the most important ones. If there’s something you think I’ve missed that deserved to be included, if you think I’ve got something wrong, or if you just want to congratulate me on a job well done then please let me know in the comments.
Mean while, if you want to go deep on another area of C#, might I recommend my recent post on using (or abusing?) Linq style foreach.
An example. Sleep is found on the Thread class. It is a static method that receives one parameter. You must either include System.Threading or call System.Threading.Thread.Sleep.
Tip: You do not need to create a new Thread to use the Sleep method as it is static.
Static
Here: We call Sleep() 3 times. The surrounding code takes the system’s time and uses Stopwatch to time the Thread.Sleep calls.
Stopwatch
C# program that sleeps
using System;
using System.Diagnostics;
using System.Threading;
class Program
{
static void Main()
{
//
// Demonstrates 3 different ways of calling Sleep.
//
var stopwatch = Stopwatch.StartNew();
Thread.Sleep
(0);
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
Console.WriteLine(DateTime.Now.ToLongTimeString());
stopwatch = Stopwatch.StartNew();
Thread.Sleep
(5000);
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
Console.WriteLine(DateTime.Now.ToLongTimeString());
stopwatch = Stopwatch.StartNew();
System.Threading.Thread.Sleep
(1000);
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
//
// Bonus: shows SpinWait method.
//
stopwatch = Stopwatch.StartNew();
Thread.SpinWait
(100000 * 10000);
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
}
}
Output
0 ElapsedMilliseconds after Sleep(0)
8:14:43 AM Time after Sleep(0)
4999 ElapsedMilliseconds after Sleep(5000)
8:14:48 AM Time after Sleep(5000)
999 ElapsedMilliseconds after Sleep(1000)
3144 ElapsedMilliseconds after SpinWait(Int32)