Magnus Mårtensson
Microsoft Regional Director, Azure MVP, CEO Loftysoft
Avirag Jain
Director & CTO R Systems
Mahesh Chand
Founder C# Corner, CEO Mindcracker
Chris Gali
CEO & Co-Founder Graphite
Subinder Khurana
Chief Architect StoryProcess, Founder NASSCOM DeepTech Club
Bryan Rishforth
Investor, Chairman Graphite
Bryn Everson
Director Biz Dev Graphite
Raj Tiwari
Digital Transformation Leader, Futurist and Visionary
Joseph Guadagno
Microsoft MVP, Lead Quicken Loans
Nikita Sachdev
Entrepreneur, Blockchain Enthusiast & Advisor, Social Media Influencer
Doug Wagner
COO & Founder Adapt Technical Group
Ritesh Modi
Architect, Senior Evangelist, Cloud Architect
Crystal Wenrick
Director Communications Mindcracker
Allen O’Neill
Microsoft MVP, Consulting Engineer/Architect
Praveen Kumar
CEO MCN Solutions
Chris Love
Founder Love2Dev, Microsoft MVP, Author
Sanjay Vyas
Microsoft Regional Director, Microsoft MVP, Founder & CEO SkillLabs Technologies
Veena Sarda
Deep Learning Consultant, Author
Sekhar Srinivasan
C# Corner MVP, Microsoft Certified Trainer, Pluralsight Author
Lalit Bansal
Founder & CEO - EIY SYS
Navdeep Garg
CEO Revinfotech
Prakash Tripathi
Tech Manager/Leader, Microsoft MVP, Blogger
Bhavna Jain
Breakthrough Consultant
Naveen Sharma
Enterprise Architect, Leadership Coach, Author
Vidya Vrat Agarwal
Principal Architect, Microsoft MVP, Author
Sheetal Agarwal
Founder Clownselors, Medical Clown, Trainer
Abhishek Kant
Founder GTM Catalyst
Vishnu Saran
Founder & CEO VoiceQube
Sandeep Soni
Founder & CEO Deccansoft, Microsoft Certified Trainer
Parveen Malik
AVP InfoSec & Vulnerability Management, Information Security Expert
Nitin Pandit
Microsoft MVP, Developer Evangelist, Author
Niloshima Srivastava
C# Corner MVP, Tech Architect, Trainer, Blogger
Bala Chirtsabesan
Senior Software Engineer at Microsoft, Author
Manoj Mittal
Sr. Technical Architect, C# Corner MVP, Author
Chandni Di
Co-Founder Voice of Slum
Vithal Wadje
Technical Lead, Microsoft MVP, Author
Shivam Ahuja
Founder SkillCircle, Business Mentor
Chervine Bhiwoo
Solution Architect, Microsoft MVP, Author
Saurabh Jain
Vice President Paytm, Founder Fun2Do Labs, Author
Vinay Solanki
Head IoT at Lenovo, Founder IoT-NCR
Anshu kumari
Founder Blockchainkids, Inventor, Trainer
Amit Singal
CEO Startup Buddy
Dev Pratap
Co-Founder & CEO Voice of Slum
Amey Vartak
Technology Consultant, Full Stack Developer, C# Corner MVP, Author
Viswanatha Swamy
Principal Software Engineer, C# Corner MVP, Author
Sanket Verma
Research Engineer @ Ballistics (Forensics) and Chair, PyData Delhi
Sourabh Somani
Lead Developer, Microsoft MVP, Author
Abhishek Mishra
Software Architect, C# Corner MVP, Author
Siddharth Vaghasia
Technical Consultant, C# Corner MVP, Blogger
Bassam Alugili
Senior Software Specialist, Database Expert
S Ravi Kumar
Solution Architect, C# Corner MVP, Author
Sundaram Subramanian
Full Stack Developer, C# Corner MVP, Speaker
Deepesh Somani
Solution Architect, Microsoft MVP, Author
Debasis Saha
Technical Project Manager, C# Corner MVP, Blogger, Author
Vipul Jain
Software Architect, C# Corner MVP, Author
Akshay Patel
Technical Architect, Microsoft Certified Trainer, C# Corner MVP, Author
Stephen Simon
RPA Developer, Evangelist, Author
Vivek Sharma
Founder Kingster636, AR/VR Specialist
Jeetendra Gund
Technical Lead, C# Corner MVP, Author
Sujal Beniwal
AI Enthusiast, Student
M Viknaraj
Microsoft MVP, Azure Architect, Author
Prasham Sabadra
Software Architect, C# Corner MVP, Trainer, Author
Aakash Maurya
Senior Developer, C# Corner MVP, Speaker
Ankit Sharma
Senior Software Engineer, C# Corner MVP, Author
Mangesh Gaherwar
Team Lead, C# Corner MVP, Author
Viral Jain
Technical Consultant, C# Corner MVP, Author
Bhasker Das
Solution Architect, Evangelist
Manish Dwivedi
Associate Project Manager
Ck Nitin
Programmer, Author
Rohit Gupta
Technical Trainer, Author
Manish Tewatia
Full-stack Marketer, UX Designer
Bhavya Gaur
Technical Illustrator
Rohit Tomar
SEO/SMO Expert
Web Track
Cloud & Data Track
Dev Track
Registration & Breakfast
Future of Desktop Apps with JS (ElectronJs)
Nitin Pandit
Building Serverless Microservices Using Microsoft Azure
Vithal Wadje
Innovating RPA: A Robot for Every Person
Stephen Simon
Managing Cloud Storage Accounts using Logic Apps
Viknaraj Manogararajah
Data visualization using Python
Sekhar Srinivasan
Going Cross platform with AR Foundation
Vivek Sharma
Keynote
Managing your Azure dependencies in ASP.NET Core apps using VS
Bala Chirtsabesan
Securing Applications on Intelligent Azure
Abhishek Mishra
Getting started with Blazor the Framework of Future
S Ravi Kumar
Lunch
Build Progressive Web Apps using Angular 9
Debasis Saha
Build and deploy to any platform using Azure DevOps
Chervine Bhiwoo
Deep Dive in Azure Service Bus
Akshay Patel
Build a Native Mobile Application using React Native and JavaScript
Joseph Guadagno
Making sense of Web Job, Web Job SDK and Functions in Azure
Prakash Tripathi
CloudFront Distribution in AWS
Viral Jain
Tea Break
Introduction to PowerBI
Aakash Maurya
Build Advanced SPFx solutions with React and Graph API
Siddharth Vaghasia
Build Business Intelligence Analyst (BIA) Skills
Sundaram Subramanian
Deep dive of Power Platform – AI BUILDER
Prasham Sabadra
Panel 1
What's new in SharePoint development
Vipul Jain
Build a SSO (Single Sign On) based Native JavaScript application with Microsoft Identity within 10 minutes
Manoj Mittal
Panel 2
Applications and working of AI
Veena Sarda
Deploying serverless API's with .Net core 3.0 on AWS & Azure
Amey Vartak
Panel 3
Blockchain with .NET Core (Ark)
Anshu Kumari
Closing Note & Prize Distribution
Dev Track
Cloud Track
Architecture Track
Emerging Tech Track
Registration & Breakfast
Creating Full-Stack Web Apps Using Server-Side Blazor
Ankit Sharma
Real time face recognition with MS Cognitive Services
Niloshima Srivastava
Building Scalable APIs with GraphQL
Jeetendra Gund
Future of development with AI and Blockchain
Navdeep Garg
Debugging Tips and Tricks with Visual Studio 2019
Joseph Guadagno
Azure Containers
Abhishek Kant
Enterprise Architecture
Naveen Sharma
Bot Framework - learn it fast and look like a boss!
Allen O’Neill
Keynote
.Net Core & C# 8 Performance
David McCarter
Working with Azure kubernetes services
Ritesh Modi
Becoming an Architect
Vidyavrat Agarwal
Why Techies Need to Learn Product Management
Saurabh Jain
Lunch
Build a rules engine in .Net Core
Sanjay Vyas
Building CI and CD Pipeline using Azure DevOps
Sandeep Soni
Entity Framework Core - Tips and Tricks, Performance Optimization, and Tuning
Bassam Alugili
Hacking your way into Data Science
Sanket Verma
Speed up your .Net Core Website
Sourabh Somani
Azure
Magnus Mårtensson
Demystifying Open Distro for Elasticsearch
Suman Debnath
Future of Data
Shivam Ahuja
Tea Break
gRPC with C# and .Net Core
Mangesh Gaherwar
Panel 1
Essentials of Cloud security
Parveen Malik
Power platform and Dynamics 365
Deepesh Somani
Microservices - the gRPC Way
Viswanatha Swamy
Panel 2
Reserved
Reserved
Closing Note & Prize Distribution
Creating A High-Resolution Stopwatch Timer In C#
A timer built with System.Diagnostics.Stopwatch gives a C# application a precise way to measure short intervals, schedule recurring work, and track elapsed time. It is especially useful when ordinary wall-clock timestamps or general-purpose UI timers introduce too much jitter for performance-sensitive code.
The approach suits software professionals working with .NET services, games, simulations, telemetry, automation, and benchmark tools. A custom stopwatch timer can measure an operation, raise a callback at a target interval, or maintain a regular schedule without relying on the system clock for elapsed duration.
Australia’s software market provides many practical use cases. A Melbourne fintech platform may need to measure transaction-processing latency, while a mining operation near Perth may monitor sensor events arriving over an unreliable network. In both cases, elapsed time and calendar time serve different purposes.
This distinction also matters for applications deployed across Sydney, Brisbane, and Adelaide. Daylight saving changes in some states, network latency across regional sites, and varying server loads can make wall-clock calculations unsuitable for interval measurement. A monotonic stopwatch is generally a safer foundation.
Why Stopwatch Is Suitable For Precise Intervals
Stopwatch uses a high-resolution performance counter when the operating system supports one. Its Frequency property reports the number of counter ticks per second, while GetTimestamp() returns the current counter value. Unlike DateTime.UtcNow, the stopwatch is designed to measure elapsed time rather than represent a calendar date.
A stopwatch is also monotonic for practical timing purposes. The system clock can be adjusted by synchronisation services, administrators, or daylight saving rules, but elapsed measurements should continue moving forward. This makes Stopwatch preferable for calculating durations, timeout windows, frame pacing, and benchmark results.
The word “tick” can be confusing in this context. A TimeSpan tick is fixed at 100 nanoseconds, whereas a stopwatch tick depends on the hardware performance counter. Converting values through Stopwatch.Frequency avoids assuming that both units are identical.
using System.Diagnostics;
long start = Stopwatch.GetTimestamp();
// Code to measure
PerformWork();
long end = Stopwatch.GetTimestamp();
double seconds = (double)(end - start) / Stopwatch.Frequency;
Console.WriteLine($"Elapsed: {seconds * 1000:F3} ms");
Designing The Timer’s Timing Model
Before writing a timer class, define what its interval means. A fixed-delay timer waits for the interval after each callback finishes. A fixed-rate timer attempts to preserve a target schedule, so the next callback is based on the original start time. Fixed-rate timing is often better for sampling and animation, but it must handle missed deadlines.
A callback that takes 40 milliseconds cannot run every 20 milliseconds on a single worker without overlap. The timer must either skip late executions, queue them, or permit concurrent callbacks. For most application services, skipping stale samples is safer than allowing an unbounded callback queue.
The following class uses a stopwatch to create a simple asynchronous periodic timer. It schedules work against a target timestamp rather than sleeping for the same duration after every callback. Task.Delay handles most of the waiting, while the stopwatch controls the elapsed-time calculation.
using System.Diagnostics;
public sealed class StopwatchTimer
{
private readonly TimeSpan _interval;
private readonly Func<CancellationToken, Task> _callback;
public StopwatchTimer(
TimeSpan interval,
Func<CancellationToken, Task> callback)
{
if (interval <= TimeSpan.Zero)
throw new ArgumentOutOfRangeException(nameof(interval));
_interval = interval;
_callback = callback ?? throw new ArgumentNullException(nameof(callback));
}
public async Task RunAsync(CancellationToken token)
{
long intervalTicks =
(long)(_interval.TotalSeconds * Stopwatch.Frequency);
long next = Stopwatch.GetTimestamp() + intervalTicks;
while (!token.IsCancellationRequested)
{
long remaining = next - Stopwatch.GetTimestamp();
if (remaining > 0)
{
double milliseconds =
remaining * 1000.0 / Stopwatch.Frequency;
await Task.Delay(
TimeSpan.FromMilliseconds(Math.Max(1, milliseconds)),
token);
}
long now = Stopwatch.GetTimestamp();
if (now >= next)
{
await _callback(token);
next += intervalTicks;
}
}
}
}
Converting Stopwatch Ticks Safely
The conversion from stopwatch ticks to seconds is straightforward:
double elapsedSeconds =
(Stopwatch.GetTimestamp() - start) / (double)Stopwatch.Frequency;
For milliseconds, multiply the result by 1,000. For microseconds, multiply by 1,000,000. Keeping the calculation in double prevents accidental integer truncation, which can hide small timing differences.
If the timer must run for a very long period, calculate carefully when converting a TimeSpan into counter ticks. Casting too early may lose precision, and multiplying large values before conversion can overflow. For ordinary intervals, the following helper is clear and adequate:
static long ToStopwatchTicks(TimeSpan interval)
{
return (long)(interval.TotalSeconds * Stopwatch.Frequency);
}
Stopwatch.Elapsed and Stopwatch.ElapsedMilliseconds are convenient when using an instance, but direct timestamp reads reduce object state and work well for a custom scheduler. A timestamp-based implementation also makes it easier to compare several checkpoints against the same timing origin.
Choosing Between Timer Mechanisms
A stopwatch does not automatically create a background thread or invoke callbacks. It is a precision measurement tool, so the application must provide the scheduling behaviour. Depending on the workload, PeriodicTimer, System.Threading.Timer, a dedicated loop, or a high-resolution busy wait may be a better fit.
The choice involves precision, CPU consumption, callback isolation, and cancellation. A desktop dashboard in Sydney may value low battery use and responsiveness, while a laboratory acquisition process may accept a dedicated core to minimise scheduling variation. No timer can guarantee exact execution when the operating system is under load.
| Mechanism | Typical precision | CPU usage | Best fit | Main limitation |
|---|---|---|---|---|
Stopwatch measurement |
High | Very low | Benchmarks and elapsed intervals | Does not schedule callbacks alone |
PeriodicTimer |
Millisecond range | Low | Async service loops | Subject to scheduler and load |
System.Threading.Timer |
Millisecond range | Low | Lightweight recurring callbacks | Overlap and disposal need care |
Task.Delay loop |
Millisecond range | Low | General asynchronous work | Delay granularity varies |
Spin wait with Stopwatch |
Very high | High | Short critical timing windows | Consumes a CPU core |
DateTime.UtcNow |
Lower for intervals | Very low | Calendar timestamps | Clock adjustments can affect results |
For most web APIs, Azure Functions, and background workers, a stopwatch-guided asynchronous loop is a sensible compromise. A hard real-time guarantee is outside the normal behaviour of Windows and .NET application scheduling, even when the counter itself has high resolution.
Preventing Drift And Overlapping Callbacks
A drifting timer waits for the callback to finish and then starts a fresh interval. Small delays accumulate, so a task intended to run every second may gradually move away from the expected schedule. Anchoring each execution to start + n × interval prevents that cumulative drift.
The timer must decide what happens after a late callback. A simple scheduler can advance next once and allow the next loop to notice that it is already late. A more defensive design can calculate how many periods have been missed and jump directly to the next future deadline.
long now = Stopwatch.GetTimestamp();
if (now >= next)
{
await callback(token);
do
{
next += intervalTicks;
}
while (next <= Stopwatch.GetTimestamp());
}
This “skip missed periods” approach is useful for telemetry and status refreshes, where current data matters more than replaying every missed tick. For financial reconciliation or queued business events, skipping may be unacceptable; those workloads need durable messages or a queue rather than a timing loop.
Never allow an asynchronous callback to overlap accidentally. If a callback can run longer than the interval, protect shared state with a lock, semaphore, channel, or single-consumer processing model. An overlapping timer may produce duplicated writes, race conditions, and misleading measurements.
Managing Resolution, Scheduling And CPU Load
High-resolution measurement does not mean high-resolution execution. Stopwatch may report very fine-grained differences, but the operating system decides when a thread actually runs. Garbage collection, CPU contention, virtual machine scheduling, power management, and other processes can all introduce jitter.
A hybrid wait can improve timing near a deadline. The loop can use Task.Delay while the remaining interval is large, then yield or briefly spin during the final fraction. Spinning should be reserved for short periods because it consumes CPU continuously and can reduce overall system performance.
while (true)
{
long remaining = deadline - Stopwatch.GetTimestamp();
if (remaining <= 0)
break;
double milliseconds =
remaining * 1000.0 / Stopwatch.Frequency;
if (milliseconds > 2)
await Task.Delay(TimeSpan.FromMilliseconds(milliseconds - 1));
else
Thread.SpinWait(100);
}
This technique may be appropriate for a short hardware-control window, but it is rarely suitable for an ordinary ASP.NET Core request or cloud worker. In Azure, extra CPU can increase cost and may provide little benefit when the process is moved between shared virtual machines.
Handling Cancellation And Resource Cleanup
A custom timer should stop predictably. Pass a CancellationToken into both the waiting operation and the callback, and treat cancellation as a normal lifecycle event. The owner can cancel the timer when a hosted service stops, a user closes a desktop application, or a monitoring session ends.
PeriodicTimer offers a useful pattern for cancellation and asynchronous disposal, even when a custom stopwatch is needed elsewhere. A custom implementation should follow the same principles: avoid fire-and-forget work, propagate cancellation, and ensure the timer does not continue after its owner has been disposed.
using var cancellation = new CancellationTokenSource();
var timer = new StopwatchTimer(
TimeSpan.FromMilliseconds(250),
async token =>
{
await CollectSampleAsync(token);
});
Task running = timer.RunAsync(cancellation.Token);
// Later:
cancellation.Cancel();
try
{
await running;
}
catch (OperationCanceledException)
{
// Expected during normal shutdown.
}
For a hosted .NET service, place the timer inside BackgroundService.ExecuteAsync and use the host-provided token. This integrates cleanly with container shutdown, deployment restarts, and service management on platforms used by teams in Brisbane, Canberra, and other Australian technology centres.
Testing Timer Accuracy In Real Conditions
A timer should be tested statistically rather than judged by a single reading. Record the actual timestamp at every callback, calculate the difference from the planned deadline, and inspect minimum, maximum, average, and percentile deviation. A result that looks accurate on an idle laptop may behave differently under production load.
Test with CPU pressure, memory allocation, network activity, and concurrent callbacks. Run the same build in Debug and Release configurations, and test on the deployment environment. Developers working with services connected through the NBN should also distinguish local scheduling delay from network round-trip time; a precise local timer cannot remove internet latency.
For a repeatable benchmark, warm up the code before recording values. JIT compilation, cache effects, connection setup, and the first garbage collection can distort early samples. Use Stopwatch around the exact operation being measured and avoid logging synchronously inside the timed region.
Practical Design Rules
- Use
StopwatchorGetTimestamp()for elapsed intervals, notDateTime.Now. - Convert counter ticks with
Stopwatch.Frequencyinstead of assuming fixed units. - Anchor recurring work to a planned schedule to reduce cumulative drift.
- Decide explicitly whether missed intervals should be skipped, queued, or processed concurrently.
- Pass cancellation tokens through waits and callbacks so shutdown is deterministic.
- Measure jitter under realistic CPU, memory, network, and deployment conditions.
A well-designed timer provides a reliable elapsed-time foundation, but it remains subject to normal operating-system scheduling. For most C# applications, combining stopwatch-based deadlines with asynchronous waiting delivers useful precision without wasting resources. Where every microsecond matters, isolate the workload, minimise allocations, and validate the result on the actual hardware and runtime used in production.
1, CBD, Maharaj Surajmal Road, Near Yamuna Sports Complex, Delhi, 110032
GENERAL QUERIES
Manish Tewatia
manish@csharpcon.com
+91-9718-431-042
TICKET QUERIES
Atul Gupta
conference@csharpcon.com
+91-9910-125-804