Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 7, 2026

Documents the behavioral change in .NET 11 Preview 1 where Environment.TickCount and Environment.TickCount64 on Windows now use QueryUnbiasedInterruptTime instead of GetTickCount64, excluding sleep/hibernation time and aligning with OS wait API behavior.

Changes

  • Created breaking change article (core-libraries/11.0/environment-tickcount-windows-behavior.md)

    • Previous behavior: Used GetTickCount64 (10-16ms resolution, included sleep time)
    • New behavior: Uses QueryUnbiasedInterruptTime (interrupt timer resolution, excludes sleep time)
    • Rationale: Consistency with Windows wait APIs (SleepEx, WaitForMultipleObjectsEx) which changed in Windows 8/Server 2012
    • Affected scenarios: Apps using higher frequency interrupt timers, code expecting timers to fire after sleep/wake cycles
  • Added .NET 11 compatibility infrastructure

    • Created 11.0.md overview page
    • Updated toc.yml with new .NET 11 section

Impact

Timers dependent on elapsed time during sleep/hibernation should migrate to DateTime.UtcNow. Code already impacted on Linux/macOS will see consistent behavior across platforms.

Original prompt

This section details on the original issue you should resolve

<issue_title>[Breaking change]: Environment.TickCount and Environment.TickCount64 made consistent with underlying OS timeout behavior</issue_title>
<issue_description>### Description

On Windows, Environment.TickCount and Environment.TickCount64 were brought inline with the behavior seen in the underlying wait APIs for the OS to no longer include sleep or hibernation time as part of the elapsed time measured. This also makes it consistent with the behavior seen on other platforms and ensures it updates at the same frequency as the underlying interrupt timer for the system allowing for higher responsiveness in apps that opted in to higher frequency updates.

Version

.NET 11 Preview 1

Previous behavior

On all platforms, Environment.TickCount simply returns the truncated result of Environment.TickCount64 and so sees identical behavior, but is subject to overflow approximately every 49 days.

On Windows, Environment.TickCount64 simply returned the result of the Win32 GetTickCount64 which updates at a fixed cadence of 10-16ms (typically 15.5ms) and included the time the system spent in sleep, hibernation, or other low-power states.

On other platforms (such as Linux and MacOS), Environment.TickCount64 updated at the same frequency as the underlying interrupt timer for the system and only includes the time the system is considered "awake".

New behavior

On all platforms, Environment.TickCount maintains its implementation and so mirrors the behavior of Environment.TickCount64.

On Windows, Environment.TickCount64 was updated to return the result of the Win32 QueryUnbiasedInterruptTime API. This brings it inline with the behavior used in the underlying wait APIs for the OS to no longer include non-awake time and update at the same frequency as the underlying interrupt timer for the system.

On other platforms, Environment.TickCount64 retains its behavior, which is inline with the new behavior on Windows.

Type of breaking change

  • Binary incompatible: Existing binaries might encounter a breaking change in behavior, such as failure to load or execute, and if so, require recompilation.
  • Source incompatible: When recompiled using the new SDK or component or to target the new runtime, existing source code might require source changes to compile successfully.
  • Behavioral change: Existing binaries might behave differently at run time.

Reason for change

Windows took a similar behavior breaking change in Win8/Server2012 and newer such that APIs which took a timeout (like SleepEx or WaitForMultipleObjectsEx) would no longer factor in non-awake time. This caused an inconsistency with .NET as such wait APIs are frequently used in conjunction with Environment.TickCount64 leading to hard to diagnose bugs such as timers firing unexpectedly.

Additionally, the underlying API used, GetTickCount64, was a less precise, only updating at a fixed resolution. This resolution was not adjusted if the underlying interrupt timer for the OS had its frequency changed which could lead to additional work being done for apps that had opted to run at a higher priority. The behavior was then also inconsistent with the behavior seen on other platforms such as MacOS and Linux.

The break therefore ensures consistency with the underlying OS and across platforms. It can also lead to higher responsiveness in apps that have opted into more frequent updates.

Recommended action

Most code should not experience any change in behavior as they will not have opted into higher frequency interrupt times, so they will continue seeing updates at the same frequency as before. However, if update frequency is relevant, users should ensure that their timeouts are passing in a correct value that meets the expectations of their code or ensure that the application is not opting into too high of a update frequency (this can only be done via P/Invoke APIs today).

Some code may see timers no longer fire immediately after a machine wakes from a sleeping or low-power state. If such time is relevant, the developer should utilize APIs such as DateTime.UtcNow to ensure such time can always be included. Such code may have to account for potential clock adjustments.

As a reminder, the behavior here is only changing on Windows and is now inline with the behavior seen on other platforms. Code that finds itself impacted by this on Windows is therefore likely already impacted by the same scenario on other platforms such as Linux and MacOS.

Feature area

Core .NET libraries

Affected APIs

System.Environment.TickCount
System.Environment.TickCount64


Associated WorkItem - 543456</issue_description>

Comments on the Issue (you are @copilot in this section)

@tannergooding @gewarren, we'...

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.


Internal previews

📄 File 🔗 Preview link
docs/core/compatibility/10.md Breaking changes in .NET 10
docs/core/compatibility/11.md Breaking changes in .NET 11
docs/core/compatibility/core-libraries/11/environment-tickcount-windows-behavior.md Environment.TickCount made consistent with Windows timeout behavior
docs/core/compatibility/toc.yml docs/core/compatibility/toc
docs/core/install/upgrade.md Upgrade to a new .NET version
docs/fundamentals/toc.yml docs/fundamentals/toc

Copilot AI self-assigned this Jan 7, 2026
…ickCount64

Co-authored-by: gewarren <24882762+gewarren@users.noreply.github.com>
Copilot AI changed the title [WIP] Update Environment.TickCount for OS consistency Add .NET 11 breaking change documentation for Environment.TickCount/TickCount64 Jan 7, 2026
Copilot AI requested a review from gewarren January 7, 2026 02:11
@gewarren gewarren marked this pull request as ready for review January 7, 2026 19:13
@gewarren gewarren requested a review from adegeo as a code owner January 7, 2026 19:13
Copilot AI review requested due to automatic review settings January 7, 2026 19:13
@gewarren gewarren requested a review from a team as a code owner January 7, 2026 19:13
@gewarren gewarren enabled auto-merge (squash) January 7, 2026 19:14
@gewarren gewarren merged commit e15439d into main Jan 7, 2026
16 checks passed
@gewarren gewarren deleted the copilot/update-environment-tickcount-behavior branch January 7, 2026 19:15
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds comprehensive documentation for a behavioral breaking change in .NET 11 Preview 1 affecting Environment.TickCount and Environment.TickCount64 on Windows. The change aligns Windows behavior with other platforms and underlying OS wait APIs by excluding sleep/hibernation time from elapsed time measurements.

  • Created breaking change documentation with detailed technical explanation of the behavior change from GetTickCount64 to QueryUnbiasedInterruptTime
  • Established .NET 11 compatibility documentation infrastructure including overview page and TOC structure
  • Updated navigation links and added redirection for deprecated file paths

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
docs/core/compatibility/core-libraries/11/environment-tickcount-windows-behavior.md New breaking change article documenting the Windows-specific behavior change with comprehensive before/after descriptions and migration guidance
docs/core/compatibility/11.md New .NET 11 breaking changes overview page following the established pattern from previous versions
docs/core/compatibility/toc.yml Added .NET 11 section and entry for the TickCount breaking change; updated .NET 10 href to use 10.md
docs/fundamentals/toc.yml Added .NET 11 breaking changes navigation entry and corrected .NET 10 reference path
docs/core/install/upgrade.md Added .NET 11 breaking changes link to "See also" section
.openpublishing.redirection.core.json Added redirection from 10.0.md to 10.md for consistency
docs/core/compatibility/10.md Removed unused no-loc entries (Blazor, Kestrel)

@@ -0,0 +1,56 @@
---
title: "Breaking change - Environment.TickCount made consistent with Windows timeout behavior"
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The title should use a colon instead of a hyphen after "Breaking change" to maintain consistency with other .NET 10 breaking change articles. Change "Breaking change -" to "Breaking change:".

Copilot uses AI. Check for mistakes.
gewarren pushed a commit to gewarren/docs that referenced this pull request Jan 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Breaking change]: Environment.TickCount and Environment.TickCount64 made consistent with underlying OS timeout behavior

3 participants