荆州哪个公司做网站11电影网
2026/1/23 10:30:09 网站建设 项目流程
荆州哪个公司做网站,11电影网,徐州建设工程招投标官方网站,建设网站公司招聘文章目录1.System.Threading.Timer(线程计时器)1.1. 方法签名1.2. 参数说明1.3. 特殊值处理1.4. 示例#xff1a;动态控制计时器2.System.Timers.Timer(服务器计时器)2.1. 示例#xff1a;定期检查服务状态3.System.Windows.Forms.Timer(Windows计时器)3.1. 示例#xff1a;…文章目录1.System.Threading.Timer(线程计时器)1.1. 方法签名1.2. 参数说明1.3. 特殊值处理1.4. 示例动态控制计时器2.System.Timers.Timer(服务器计时器)2.1. 示例定期检查服务状态3.System.Windows.Forms.Timer(Windows计时器)3.1. 示例更新 WinForms 界面上的时间标签System.Windows.Threading.DispatcherTimer4.1. 示例更新 WPF 界面上的数据显示5.计时器核心区别线程模型与精度5.1. 线程模型5.2. 计时精度1. 后台计时器System.Threading.Timer (线程池高精度)2. 后台计时器System.Timers.Timer (事件驱动线程池)3. UI 计时器System.Windows.Forms.Timer (WinForms消息循环)4. UI 计时器System.Windows.Threading.DispatcherTimer (WPF调度器)5.3. 如何进行跨线程操作 (后台 - UI)6.Stopwatch类 (System.Diagnostics.Stopwatch)核心用途关键特点主要方法和属性示例测量代码块耗时Stopwatch vs. Timer7.精确计时器7.1. 调用WIN API中的GetTickCount介绍优点与缺点总结7.2. timeGetTime (WIN API - 可调精度计时)介绍优点与缺点总结7.3. System.Environment.TickCount (.NET 封装 - 粗略计时)介绍优点与缺点总结7.4. QueryPerformanceCounter (Windows API - 高分辨率计数器)介绍优点与缺点总结7.5. System.Diagnostics.Stopwatch (.NET 推荐 - 高精度封装)介绍优点与缺点总结7.6. CPU 时间戳 (Read Time-Stamp Counter, RDTSC)介绍优点与缺点总结最终结论和对比1.System.Threading.Timer(线程计时器)1、最底层、轻量级的计时器。基于线程池实现的工作在辅助线程。2、它并不是内在线程安全的并且使用起来比其他计时器更麻烦。此计时器通常不适合 Windows 窗体环境。// ctorpublicTimer(TimerCallbackcallback,objectstate,intdueTime,intperiod);线程模型在线程池线程上执行回调方法TimerCallback委托。特点这是一个轻量级的计时器设计用于在多线程环境或服务器环境如服务、控制台应用中进行高精度、非 UI的定期操作。执行方式它不涉及事件而是直接调用一个TimerCallback委托。回调方法的执行会占用一个线程池线程。注意由于回调方法在后台线程执行它不能直接操作 UI 元素否则会导致跨线程异常。后台任务调度usingSystem;usingSystem.Threading;publicclassThreadingTimerExample{privatestaticTimer_timer;publicstaticvoidRun(){Console.WriteLine($主线程启动于:{DateTime.Now:HH:mm:ss.fff});// 创建 Timer// 1. TimerCallback 方法// 2. 传递给回调方法的 object 状态对象这里传递 null// 3. 第一次调用前的延迟时间 (dueTime)1000 毫秒// 4. 后续调用之间的间隔时间 (period)2000 毫秒_timernewTimer(TimerTask,null,1000,2000);// 保持主程序运行以便 Timer 可以继续执行Console.WriteLine(按 Enter 键退出程序...);Console.ReadLine();// 停止并释放计时器_timer.Dispose();Console.WriteLine(计时器已停止。);}// TimerCallback 方法在线程池线程上执行privatestaticvoidTimerTask(objectstate){Console.WriteLine($Timer 任务执行于:{DateTime.Now:HH:mm:ss.fff}线程 ID:{Thread.CurrentThread.ManagedThreadId});// 可以在这里执行短时间的后台任务}}1.1. 方法签名publicboolChange(intdueTime,intperiod);// 或者使用 TimeSpan 版本更精确、更安全publicboolChange(TimeSpandueTime,TimeSpanperiod);1.2. 参数说明参数类型含义dueTimeint (毫秒) 或 TimeSpan第一次调用回调方法前的延迟时间。periodint (毫秒) 或 TimeSpan后续调用回调方法之间的间隔时间。1.3. 特殊值处理dueTime和period都可以接受特殊值用于控制计时器的行为值含义效果0零0表示立即调用回调方法。-1负一-1dueTime为 -1 时表示计时器已禁用不会触发回调方法。-1负一-1period为 -1 时表示计时器只触发一次之后自动禁用单次模式。Timeout.Infinite常量 (-1)与使用 -1 效果相同是更清晰的表达方式。1.4. 示例动态控制计时器下面的例子演示了如何使用Change方法首先让计时器以 2 秒的间隔运行几次然后将它切换到 5 秒的间隔最后将它停止。usingSystem;usingSystem.Threading;publicclassThreadingTimerChangeExample{privatestaticTimer_timer;privatestaticint_counter0;publicstaticvoidRun(){Console.WriteLine($计时器启动。初始间隔2秒。);// 初始设置1秒后第一次执行之后每隔 2000 毫秒执行一次_timernewTimer(TimerTask,null,1000,2000);// 保持程序运行Console.WriteLine(按 Enter 键观察变化和停止...);Console.ReadLine();// 确保计时器停止并释放资源_timer.Dispose();Console.WriteLine(程序退出。);}privatestaticvoidTimerTask(objectstate){_counter;Console.WriteLine($[{DateTime.Now:HH:mm:ss}] 任务执行{_counter}次。 线程ID:{Thread.CurrentThread.ManagedThreadId});if(_counter3){// 达到 3 次后我们使用 Change 方法改变计时器的间隔// 新设置5000 毫秒5秒后第一次执行之后每隔 5000 毫秒执行一次_timer.Change(5000,5000);Console.ForegroundColorConsoleColor.Yellow;Console.WriteLine(--- 计时器间隔已修改为 5 秒 ---);Console.ResetColor();}if(_counter5){// 达到 5 次后我们使用 Change 方法停止计时器// 设置 dueTime 和 period 都为 -1停止触发_timer.Change(Timeout.Infinite,Timeout.Infinite);Console.ForegroundColorConsoleColor.Red;Console.WriteLine(--- 计时器已停止 (通过 Change 方法) ---);Console.ResetColor();}}}// 运行输出示例 (时间戳会有变化):// 计时器启动。初始间隔2秒。// 按 Enter 键观察变化和停止...// [10:00:01] 任务执行 1 次。 线程ID: 7// [10:00:03] 任务执行 2 次。 线程ID: 8// [10:00:05] 任务执行 3 次。 线程ID: 7// --- 计时器间隔已修改为 5 秒 ---// [10:00:10] 任务执行 4 次。 线程ID: 8 // 等待了 5 秒// [10:00:15] 任务执行 5 次。 线程ID: 7 // 又等待了 5 秒// --- 计时器已停止 (通过 Change 方法) ---使用Change方法是控制System.Threading.Timer行为的标准和推荐方式。2.System.Timers.Timer(服务器计时器)针对服务器的服务程序基于System.Threading.Timer被设计并优化成能用于多线程环境。在这种情况下应该确保事件处理程序不与 UI 交互。在asp.net中一般使用System.Timers.Timer。继承自Compnent公开了可以SynchronizingObject 属性避免了线程池中无法访问主线程中组件的问题模拟System.Windows.Forms.Timer单线程模式。但是除非需要对事件的时间安排进行更精确的控制否则还是应该改为使用 System.Windows.Forms.Timer。AutoReset属性设置计时器是否在引发Elapsed事件后重新计时默认为true。如果该属性设为False,则只执行timer_Elapsed方法一次。System.Timers.Timer是多线程定时器如果一个Timer没有处理完成到达下一个时间点新的Timer同样会被启动。所以Timer比较适合执行不太耗时的小任务若在Timer中运行耗时任务很容易出现由于超时导致的多线程重入问题即多个线程同时进入timer_Elapsed方法。为了应对多线程重入问题。可以加锁也可以增加标志位。 Interlocked.Exchange提供了一种轻量级的线程安全的给对象赋值的方法所以使用Interlocked.Exchange给变量赋值。线程模型默认情况下在线程池线程上引发Elapsed事件。特点这是一个事件驱动的计时器设计用于多线程环境或服务器应用例如服务或控制台应用。它比System.Threading.Timer更易于使用因为它使用标准的 .NET 事件模型。执行方式当间隔时间到达时它会引发Elapsed事件该事件的处理程序默认在线程池线程上执行。它有一个AutoReset属性可以控制事件是否重复触发。注意与System.Threading.Timer类似由于事件处理程序在后台线程执行它不能直接操作 UI 元素。2.1. 示例定期检查服务状态usingSystem;usingSystem.Timers;publicclassTimersTimerExample{privatestaticTimer_aTimer;publicstaticvoidRun(){// 实例化 Timer并设置间隔为 3000 毫秒 (3 秒)_aTimernewSystem.Timers.Timer(3000);// 关联 Elapsed 事件的处理方法_aTimer.ElapsedOnTimedEvent;// 设置为重复引发事件 (默认为 true)_aTimer.AutoResettrue;// 启动计时器_aTimer.Enabledtrue;Console.WriteLine(服务器计时器已启动。按 Enter 键退出...);Console.ReadLine();// 停止并释放计时器_aTimer.Enabledfalse;_aTimer.Dispose();Console.WriteLine(计时器已停止。);}privatestaticvoidOnTimedEvent(Objectsource,ElapsedEventArgse){// 此代码在线程池线程上执行Console.WriteLine($检查系统状态于:{e.SignalTime:HH:mm:ss.fff});// 模拟执行一些检查操作比如检查数据库连接、日志记录等。}}3.System.Windows.Forms.Timer(Windows计时器)此计时器直接继承自Component它经过了专门的优化以便与 Windows 窗体一起使用并且必须在窗口中使用。Windows计时器建立在基于消息的UI线程上运行精度限定为5ms。Tick事件中执行的事件与主窗体是同一个线程单线程并且对与 UI 交互是安全的。只有Enable和Internal两个属性和一个Tick事件可以使用Start和Stop方法控制Enable属性。线程模型仅在UI 线程上执行且需要一个活动的 UI 消息循环即 WinForms 应用。特点专为Windows Forms应用程序设计。它的计时精度较低受限于 WinForms 消息循环的频率但最大的优点是它安全地访问 UI 元素因为它的Tick事件始终在创建它的 UI 线程上触发。执行方式当间隔时间到达时它会在 UI 线程的消息队列中放置一个消息导致Tick事件被触发。3.1. 示例更新 WinForms 界面上的时间标签假设你在一个 WinForms 应用中有一个Label控件名为timeLabel。// 这是一个 WinForms 窗体类中的代码片段// 声明 Timer 变量privateSystem.Windows.Forms.Timer_formsTimer;privatevoidForm1_Load(objectsender,EventArgse){_formsTimernewSystem.Windows.Forms.Timer();// 设置间隔为 1000 毫秒 (1 秒)_formsTimer.Interval1000;// 关联 Tick 事件的处理方法_formsTimer.TickFormsTimer_Tick;// 启动计时器_formsTimer.Start();}privatevoidFormsTimer_Tick(objectsender,EventArgse){// 此代码在 UI 线程上执行可以直接更新 UI 元素timeLabel.TextDateTime.Now.ToLongTimeString();}// 停止时可以调用 _formsTimer.Stop();System.Windows.Threading.DispatcherTimer主要用于WPF中。属性和方法与System.Windows.Forms.Timer类似。DispatcherTimer中Tick事件执行是在主线程中进行的。使用DispatcherTimer时有一点需要注意因为DispatcherTimer的Tick事件是排在Dispatcher队列中的当系统在高负荷时不能保证在Interval时间段执行可能会有轻微的延迟但是绝对可以保证Tick的执行不会早于Interval设置的时间。如果对Tick执行时间准确性高可以设置DispatcherTimer的priority。线程模型仅在与关联的Dispatcher 线程上执行通常是 WPF/UWP/WinUI 的UI 线程。特点专为WPF应用程序设计。它与System.Windows.Forms.Timer的目的类似——安全地与 UI 交互但它与 WPF 的Dispatcher机制集成可以指定执行的优先级。它的精度通常优于System.Windows.Forms.Timer。执行方式当间隔时间到达时它将一个操作加入到 Dispatcher 队列中然后操作在 UI 线程上以指定的优先级执行触发Tick事件。4.1. 示例更新 WPF 界面上的数据显示假设你在一个 WPF 窗口中有一个TextBlock控件名为statusText。usingSystem;usingSystem.Windows.Threading;usingSystem.Windows.Controls;// 用于 TextBlock// 这是一个 WPF 窗口类中的代码片段// 声明 DispatcherTimer 变量privateDispatcherTimer_dispatcherTimer;privateTextBlockstatusText;// 假设这是 UI 上的一个元素publicMainWindow(){InitializeComponent();// 假设 statusText 已在 XAML 中定义并初始化_dispatcherTimernewDispatcherTimer();// 设置间隔为 500 毫秒 (0.5 秒)_dispatcherTimer.IntervalTimeSpan.FromMilliseconds(500);// 关联 Tick 事件的处理方法_dispatcherTimer.TickDispatcherTimer_Tick;// 启动计时器_dispatcherTimer.Start();}privatevoidDispatcherTimer_Tick(objectsender,EventArgse){// 此代码在 UI 线程上执行可以直接更新 UI 元素statusText.Text$当前时间:{DateTime.Now:HH:mm:ss.fff}\nUI 刷新中...;}// 停止时可以调用 _dispatcherTimer.Stop();总结非 UI 任务服务、控制台应用、后台工作高精度、轻量级、直接回调选择System.Threading.Timer。事件驱动、易于使用、需要AutoReset选择System.Timers.Timer。Windows UI 应用中的 UI 更新WinForms 应用选择System.Windows.Forms.Timer。WPF/UWP/WinUI 应用选择System.Windows.Threading.DispatcherTimer。计时器类命名空间适用环境线程模型精度/特点典型用途System.Threading.TimerSystem.Threading服务、控制台应用、多线程环境线程池线程 (后台线程)高精度适用于短时间的非 UI 操作后台任务、调度、轮询System.Timers.TimerSystem.Timers服务、控制台应用、多线程环境线程池线程 (后台线程)高精度事件驱动具有 AutoReset 属性定期检查、服务任务、触发事件System.Windows.Forms.TimerSystem.Windows.FormsWindows Forms (WinForms) UI 应用UI 线程 (单线程)精度较低受 UI 消息循环限制安全访问 UIUI 更新、动画、状态栏刷新System.Windows.Threading.DispatcherTimerSystem.Windows.ThreadingWindows Presentation Foundation (WPF) UI 应用UI 线程 (单线程)精度较高受 Dispatcher 队列限制安全访问 UIUI 更新、动画、实时数据显示5.计时器核心区别线程模型与精度5.1. 线程模型这是四种计时器最根本的区别直接决定了它们的应用场景UI vs. 后台。计时器类运行线程核心机制UI 访问安全性System.Threading.Timer线程池线程采用 TimerCallback 委托由 CLR 线程池调度执行。不安全。必须手动使用 Invoke/Dispatcher 机制切换到 UI 线程。System.Timers.Timer线程池线程引发 Elapsed 事件默认由 CLR 线程池线程处理。不安全。原因同上。System.Windows.Forms.TimerUI 线程依赖 WinForms 的消息循环Message Loop。它向消息队列发送一个计时消息。安全。Tick 事件总是在创建它的 UI 线程上执行。System.Windows.Threading.DispatcherTimerUI 线程依赖 WPF 的Dispatcher 队列。它将操作加入到 Dispatcher 队列中执行。安全。Tick 事件总是在关联的 Dispatcher 线程上执行。总结线程模型后台型 (Threading Timers)运行在线程池上适用于高并发、服务器或后台任务。UI 型 (Forms Dispatcher)运行在单个 UI 线程上适用于需要频繁更新界面的场景。5.2. 计时精度计时器的“精度”指的是它触发事件或回调的时间偏差即实际触发时间与设定时间之间的差异。计时器类精度特点性能开销适用场景System.Threading.Timer最高基于内核 I/O 完成端口高效率。最轻量级。只涉及一个回调方法。对时间要求严格的后台调度。System.Timers.Timer较高基于内核但略低于 Threading.Timer。较高。涉及事件封装和锁定机制。后台调度但更喜欢事件模型。System.Windows.Forms.Timer最低受限于 UI 消息循环频率。轻量级但效率受 UI 忙碌程度影响。只需要大约每秒几次的简单 UI 更新。System.Windows.Threading.DispatcherTimer较高受限于 Dispatcher 队列。中等。可以设置优先级影响精度。需要更精确的 WPF 动画或实时数据更新。关键点 UI 计时器 (Forms.Timer, DispatcherTimer) 的精度永远受限于 UI 线程的繁忙程度。如果 UI 线程正在执行耗时的操作例如一个长时间的按钮点击处理计时器事件就会被延迟。后台计时器则没有这个问题。1. 后台计时器System.Threading.Timer(线程池高精度)优点精度高开销低最适合在无 UI 环境中或作为复杂多线程应用的一部分使用。缺点无法直接访问 UI。如果回调方法执行时间过长会阻塞线程池中的其他任务。示例应用数据库连接池的超时检测、短时间的后台数据同步、自定义调度器。2. 后台计时器System.Timers.Timer(事件驱动线程池)优点使用标准的Elapsed事件编码更自然、更方便。缺点无法直接访问 UI。默认情况下事件处理程序在后台线程运行如果需要操作 UI需要使用SynchronizationContext或Control.Invoke。示例应用服务中定期写日志文件、检查外部设备状态、易于管理的周期性任务。3. UI 计时器System.Windows.Forms.Timer(WinForms消息循环)优点自动保证线程安全可直接操作 WinForms 控件。缺点精度低最低可达 50ms 左右在繁忙时更差。示例应用简单的时钟显示、状态栏更新、控制简单的 WinForms 动画。4. UI 计时器System.Windows.Threading.DispatcherTimer(WPF调度器)优点自动保证线程安全可直接操作 WPF 控件精度相对较高可以设置DispatcherPriority来优化性能。缺点仅限 WPF/UWP/WinUI 应用。示例应用复杂的 WPF 动画、实时图表更新、用户操作的防抖处理。5.3. 如何进行跨线程操作 (后台 - UI)如果你必须使用高精度的后台计时器System.Threading.Timer或System.Timers.Timer来触发 UI 更新你必须手动切换到 UI 线程。在 WinForms 中使用Control.Invoke()或Control.BeginInvoke()。在 WPF 中使用Dispatcher.Invoke()或Dispatcher.BeginInvoke()。跨线程访问 UI 示例WPF// 假设这是在 WPF 中使用后台计时器 (System.Timers.Timer)privatestaticSystem.Timers.Timer_aTimer;privateTextBlock_statusText;// UI 控件privatevoidInitializeTimer(System.Windows.Threading.Dispatcherdispatcher){_aTimernewSystem.Timers.Timer(100);// 高频后台计时器_aTimer.Elapsed(s,e){// **错误的做法**_statusText.Text 更新; (会抛出跨线程异常)// **正确的做法**使用 Dispatcher 切换回 UI 线程dispatcher.Invoke((){_statusText.Text$后台计时器触发于:{DateTime.Now.ToLongTimeString()};});};_aTimer.Start();}6.Stopwatch类 (System.Diagnostics.Stopwatch)Stopwatch 不是一个定时器Timer它不会在固定间隔触发事件或回调。它是一个高精度、高性能的工具专门用于测量代码执行的时间间隔即耗时。Stopwatch 实例可以测量一个时间间隔的运行时间也可以测量多个时间间隔的总运行时间。 在典型的 Stopwatch 方案中先调用 Start 方法然后调用 Stop 方法最后使用 Elapsed 属性检查运行时间。Stopwatch 实例或者在运行或者已停止使用IsRunning可以确定 Stopwatch 的当前状态。使用 Start 可以开始测量运行时间使用 Stop 可以停止测量运行时间。通过属性 Elapsed、ElapsedMilliseconds 或 ElapsedTicks 查询运行时间值。当实例正在运行或已停止时可以查询运行时间属性。运行时间属性在 Stopwatch 运行期间稳固递增在该实例停止时保持不变。默认情况 下Stopwatch 实例的运行时间值相当于所有测量的时间间隔的总和。每次调用 Start 时开始累计运行时间计数每次调用 Stop 时结束当前时间间隔测量并冻结累计运行时间值。使用 Reset 方法可以清除现有 Stopwatch 实例中的累计运行时间。Stopwatch在基础计时器机制中对计时器的刻度进行计数从而测量运行时间。如果安装的硬件和操作系统支持高分辨率性能的计数器则 Stopwatch 类将使用该计数器来测量运行时间否则Stopwatch 类将使用系统计数器来测量运行时间。使用Frequency和IsHighResolution字段可以确定实现 Stopwatch 计时的精度和分辨率。核心用途Stopwatch最主要的用途是性能分析Profiling和代码耗时测量。它可以精确测量一段代码块或一个操作从开始到结束所花费的实际时间。关键特点高精度Stopwatch使用系统的高分辨率性能计数器如果可用通常以纳秒nanosecond级别计时因此它的精度远高于前面讨论的四种计时器。不涉及线程/消息循环它是一个独立的测量工具与计时器的线程模型UI 线程或线程池无关它只是记录时间戳。简单易用通过Start()、Stop()和Reset()等方法进行控制。主要方法和属性方法/属性类型描述Start()方法开始或恢复测量时间。Stop()方法停止测量时间。Reset()方法停止测量并将已记录的时间清零。Restart()方法停止、清零然后重新开始测量。相当于 Reset() Start()。IsRunning属性获取 Stopwatch 是否正在运行的布尔值。Elapsed属性获取当前已过去的时间间隔返回一个 TimeSpan 对象。ElapsedMilliseconds属性获取当前已过去的总毫秒数long。ElapsedTicks属性获取当前已过去的总计数器刻度数long。示例测量代码块耗时这个例子演示了如何使用Stopwatch来测量一个简单的循环操作的执行时间。usingSystem;usingSystem.Diagnostics;usingSystem.Threading;publicclassStopwatchExample{publicstaticvoidRun(){// 1. 创建并启动一个新的 Stopwatch 实例StopwatchstopwatchnewStopwatch();stopwatch.Start();Console.WriteLine(Stopwatch 已启动...);// 2. 执行需要计时的代码块模拟一个耗时操作longsum0;for(inti0;i100000;i){sumi;// 模拟一些计算延迟Thread.SpinWait(50);}// 3. 停止测量stopwatch.Stop();// 4. 读取结果TimeSpantsstopwatch.Elapsed;Console.WriteLine($\n代码块执行完毕计算结果为:{sum});Console.WriteLine(------------------------------------------);Console.WriteLine($总耗时 (TimeSpan):{ts});Console.WriteLine($总耗时 (毫秒):{stopwatch.ElapsedMilliseconds}ms);Console.WriteLine($总耗时 (Ticks):{stopwatch.ElapsedTicks}ticks);// 5. 重新开始测量 (可选)stopwatch.Restart();Console.WriteLine(\nStopwatch 已 Restart。);// ... 执行另一个操作 ...// stopwatch.Stop();}}Stopwatch vs. Timer特性StopwatchTimer (所有类型)用途测量已发生的时间间隔耗时。在未来某个时间点或周期性地触发一个动作。机制记录高性能计数器的值。依赖操作系统或消息循环的调度。精度极高纳秒级不受 CPU 负载影响。中等到较低毫秒级受线程模型和负载影响。事件/回调无。仅提供时间数据。有。通过事件 (Tick/Elapsed) 或回调 (TimerCallback) 触发代码执行。总结来说如果你想知道一个操作花了多长时间请用Stopwatch如果你想在某个时间点或周期性地做某事请用Timer。7.精确计时器7.1. 调用WIN API中的GetTickCount[DllImport(kernel32)]static extern uint GetTickCount();从操作系统启动到现在所经过的毫秒数精度为1毫秒经简单测试发现其实误差在大约在15ms左右介绍机制调用 Windows 内核 API返回系统启动后经过的毫秒数。精度宣称 1 毫秒。但在实际 Windows 环境中其底层时钟周期Timer Resolution通常默认在10ms 到 15.6ms左右所以您测试出的 15ms 左右的误差是正常的。用途主要用于判断系统是否运行了足够长的时间或者进行非常粗略的时间间隔测量。优点与缺点优点简单易用不需要特殊权限。缺点精度低不适用于需要高精度测量的场景。溢出限制返回值为uint(32位无符号整数)在大约 49.7 天后会溢出归零。总结场景粗略计时、判断超时短于 49 天。不适用于性能测量或高精度定时。用法// uint s1 GetTickCount();Thread.Sleep(2719);Console.WriteLine(GetTickCount() - s1); //单位毫秒usingSystem;usingSystem.Runtime.InteropServices;usingSystem.Threading;publicclassGetTickCountExample{[DllImport(kernel32)]staticexternuintGetTickCount();publicstaticvoidMeasureSleep(){uintstartGetTickCount();Thread.Sleep(1234);uintendGetTickCount();// 由于返回 uint可以直接相减得到毫秒差uintelapsedMsend-start;Console.WriteLine(--- 1. GetTickCount ---);Console.WriteLine($测量耗时:{elapsedMs}毫秒);Console.WriteLine($**注意:** 精度低 (通常 ~10-15ms)结果可能不精确。);}}7.2. timeGetTime (WIN API - 可调精度计时)[DllImport(winmm)]staticexternuinttimeGetTime();常用于多媒体定时器中与GetTickCount类似也是返回操作系统启动到现在所经过的毫秒数精度为1毫秒。一般默认的精度不止1毫秒不同操作系统有所不同需要调用timeBeginPeriod与timeEndPeriod来设置精度介绍机制与GetTickCount类似也是返回系统启动后经过的毫秒数。但它属于多媒体扩展的一部分。精度默认精度与GetTickCount类似。核心特性可以通过调用timeBeginPeriod(t)和timeEndPeriod(t)来修改系统计时器分辨率。将分辨率设置为 1ms 后timeGetTime的精度会得到显著提高以及您观察到的GetTickCount和Environment.TickCount的精度也会提高。优点与缺点优点通过timeBeginPeriod可以临时提升系统计时器的精度对于需要 1ms 精度的应用如多媒体处理非常有用。缺点精度提升代价提升精度会增加系统的功耗和 CPU 负载因为内核时钟中断频率增加。溢出限制同样受限于 32 位返回值约 49.7 天。总结场景1ms 精度定时、多媒体应用。注意使用完毕后必须调用timeEndPeriod恢复系统默认精度。usingSystem;usingSystem.Runtime.InteropServices;usingSystem.Threading;publicclassTimeGetTimeExample{[DllImport(winmm)]staticexternuinttimeGetTime();[DllImport(winmm)]staticexternvoidtimeBeginPeriod(intt);[DllImport(winmm)]staticexternvoidtimeEndPeriod(intt);publicstaticvoidMeasureSleepWithHighRes(){// 尝试将系统计时器分辨率设置为 1 毫秒timeBeginPeriod(1);uintstarttimeGetTime();Thread.Sleep(1234);uintendtimeGetTime();timeEndPeriod(1);// 务必恢复系统默认精度uintelapsedMsend-start;Console.WriteLine(\n--- 2. timeGetTime (高精度模式) ---);Console.WriteLine($测量耗时:{elapsedMs}毫秒);Console.WriteLine($**注意:** 精度已通过 timeBeginPeriod 提升。);}}7.3. System.Environment.TickCount (.NET 封装 - 粗略计时)介绍机制 .NET 运行时对系统 API 的封装。它在内部确实调用了类似的系统启动时间 API很可能就是 GetTickCount。返回值疑问解答GetTickCount 和 timeGetTime 原型返回 DWORD (32位无符号)在 C# 中对应 uint。System.Environment.TickCount返回int(32位有符号)。原因.NET 框架为了简便和兼容性将返回值强制转换为int。这意味着它在约24.8 天时就会从最大正数溢出到最小负数。对于测量时间差来说只要时间差小于 24.8 天减法计算是正确的因为溢出遵循模运算但处理起来更麻烦。优点与缺点优点最简单的 .NET 调用方式不需要 P/Invoke。缺点精度低默认精度与GetTickCount相同。溢出更早溢出周期比GetTickCount短一半约 24.8 天。总结场景最简单的粗略计时不推荐用于生产环境的长时间运行系统或高精度测量。usingSystem;usingSystem.Threading;publicclassEnvironmentTickCountExample{publicstaticvoidMeasureSleep(){// 返回值是 intintstartEnvironment.TickCount;Thread.Sleep(1234);intendEnvironment.TickCount;// C# 的 int 减法可以正确处理 32 位溢出只要时间差小于 24.8 天intelapsedMsend-start;Console.WriteLine(\n--- 3. System.Environment.TickCount ---);Console.WriteLine($测量耗时:{elapsedMs}毫秒);Console.WriteLine($**注意:** 精度低且 24.8 天后溢出。);}}7.4.QueryPerformanceCounter(Windows API - 高分辨率计数器)介绍机制调用 Windows 内核 API获取硬件级别的高性能计数器的当前值。频率 (QueryPerformanceFrequency):获取该计数器每秒增加的次数通常为 MHz 级别百万赫兹。精度极高通常可达纳秒或微秒级别是 Windows 提供的最高精度计时工具。优点与缺点优点精度高返回值是long(64位)几乎不会溢出。缺点兼容性问题需要硬件支持虽然现代硬件几乎都支持。硬件依赖性您提到的“节能模式/超频模式/电源模式”问题确实存在于较旧的或配置不良的系统上。这些问题通常与 CPU 频率变化和多核系统的计数器同步有关。现代 Windows 版本和硬件如使用 HPET/ACPI-PM已大大缓解这些问题但在跨机器测试时仍需注意。总结场景毫秒以下级别的高精度性能测量是实现高精度计时的核心。使用 P/Invoke 调用QueryPerformanceFrequency获取频率再调用QueryPerformanceCounter测量时间。usingSystem;usingSystem.Runtime.InteropServices;usingSystem.Threading;publicclassQPCExample{[DllImport(kernel32.dll)]staticexternboolQueryPerformanceFrequency(reflonglpPerformanceFrequency);[DllImport(kernel32.dll)]staticexternboolQueryPerformanceCounter(reflonglpPerformanceCount);publicstaticvoidMeasureSleep(){longfrequency0;QueryPerformanceFrequency(reffrequency);longstartCount0;QueryPerformanceCounter(refstartCount);Thread.Sleep(1234);longendCount0;QueryPerformanceCounter(refendCount);// 计算公式秒 (计数差 / 频率)decimalelapsedSeconds(decimal)(endCount-startCount)/(decimal)frequency;Console.WriteLine(\n--- 4. QueryPerformanceCounter ---);Console.WriteLine($频率:{frequency}计数/秒);Console.WriteLine($测量耗时:{elapsedSeconds:F6}秒);Console.WriteLine($**特点:** 极高精度以硬件频率为基准。);}}7.5.System.Diagnostics.Stopwatch(.NET 推荐 - 高精度封装)介绍机制这是 .NET 推荐的计时器类。它内部自动封装和管理了QueryPerformanceCounter。IsHighResolution属性可以告诉你底层是否使用了QueryPerformanceCounter通常为true。如果不支持高性能计数器它会回退到使用DateTime.Ticks或其他较慢但可靠的系统计数器。优点结合了QueryPerformanceCounter的高精度和 .NET 的易用性并自动处理了复杂的 API 调用和兼容性问题。优点与缺点优点最佳实践。高精度、易用、线程安全、自动处理底层兼容性。缺点依赖底层硬件的稳定性因此继承了QueryPerformanceCounter潜在的硬件依赖性问题但在应用层面这是最可靠的选择。总结场景.NET 环境下进行代码性能测量、任何需要高精度计时的场景。使用 .NET 推荐的Stopwatch类。这是对QueryPerformanceCounter的最佳封装。usingSystem;usingSystem.Diagnostics;usingSystem.Threading;publicclassStopwatchExample{publicstaticvoidMeasureSleep(){StopwatchswnewStopwatch();Console.WriteLine(\n--- 5. System.Diagnostics.Stopwatch (推荐) ---);Console.WriteLine($高分辨率支持:{Stopwatch.IsHighResolution});Console.WriteLine($频率:{Stopwatch.Frequency}计数/秒);sw.Start();Thread.Sleep(1234);sw.Stop();// 直接获取 TimeSpanTimeSpanelapsedTssw.Elapsed;Console.WriteLine($测量耗时 (TimeSpan):{elapsedTs});Console.WriteLine($测量耗时 (秒):{sw.ElapsedTicks/(double)Stopwatch.Frequency:F6}秒);Console.WriteLine($**特点:** 高精度易用.NET 性能测量的首选。);}}7.6. CPU 时间戳 (Read Time-Stamp Counter, RDTSC)介绍机制直接读取 CPU 内部的时间戳计数器 (TSC)。这是一个在每个时钟周期递增的寄存器。精度理论上的最高精度可达纳秒 (ns)级别。实现需要使用内联汇编如您所示的 C 托管代码或特殊的外部库来实现RDTSC指令。优点与缺点优点极高的理论精度和最小的 API 调用开销。缺点复杂性需要 C/汇编代码不易于纯 C# 项目使用。不稳定/不可靠这是最大的问题。TSC 的频率受 CPU 频率缩放SpeedStep、Turbo Boost、节能模式等的影响。在多核/多 CPU 系统中不同核心的 TSC 可能不同步。这使得它在现代通用操作系统中不适合作为可靠的时间测量基准。需要校准必须使用QueryPerformanceFrequency的值来将时钟周期Ticks转换为实际时间秒这使得它并没有比QueryPerformanceCounter简单多少。总结场景仅适用于底层驱动程序、嵌入式系统或非常专业的微基准测试且需要严格控制 CPU 频率和核心同步的环境。不建议在普通应用程序中使用。由于 C# 不支持内联汇编此方法需要依赖 C 编译的 DLL在纯 C# 环境中实现过于复杂且不推荐。这里仅提供一个简化的 C#调用示例假设已经有了一个能够获取 TSC 计数值的GetCycleCount()方法。// 假设已经通过 P/Invoke 导入了一个外部 DLL 中的 GetCycleCount 方法// 假设 QueryPerformanceFrequency 已经获取了 QPC 的频率usingSystem;usingSystem.Runtime.InteropServices;usingSystem.Threading;publicclassRDTSCExample{// 假设这是从 C DLL 导入的方法[DllImport(MyTimerDll.dll)]staticexternulongGetCycleCount();publicstaticvoidMeasureSleep(longqpcFrequency){try{ulongstartCyclesGetCycleCount();Thread.Sleep(1234);ulongendCyclesGetCycleCount();// 计算公式秒 (周期差 / 频率)这里的频率应该是 CPU 的实际运行频率// 但为简化我们使用 QPC 的频率进行粗略转换实际中这种混合转换会导致不准确decimalelapsedSeconds(decimal)(endCycles-startCycles)/(decimal)qpcFrequency;Console.WriteLine(\n--- 6. CPU 时间戳 (RDTSC) ---);Console.WriteLine($测量周期数:{endCycles-startCycles});Console.WriteLine($测量耗时 (基于QPC频率):{elapsedSeconds:F6}秒);Console.WriteLine($**特点:** 理论精度最高但**结果极不稳定**且难以在纯 C# 中使用。);}catch(DllNotFoundException){Console.WriteLine(\n--- 6. CPU 时间戳 (RDTSC) ---);Console.WriteLine(跳过该方法需要外部 C 编译的 DLL通常不用于常规 C# 应用。);}}}最终结论和对比方法类型精度级别溢出/限制推荐场景GetTickCountWIN API粗糙 (~10-15ms)49.7 天溢出最简单的粗略计时timeGetTimeWIN API粗糙可提升至 1ms49.7 天溢出需 1ms 精度且可接受功耗增加的多媒体应用Environment.TickCount.NET 封装粗糙 (~10-15ms)24.8 天溢出不推荐使用QueryPerformanceCounterWIN API极高(微秒/纳秒)64 位无溢出底层高精度计时实现System.Diagnostics.Stopwatch.NET 封装极高(微秒/纳秒)64 位无溢出常规应用中高精度测量的首选CPU Time Stamp (RDTSC)汇编指令理论最高 (纳秒)不稳定需 C仅用于专业微基准测试或内核级应用对于常规应用中的定时触发System.Timers.Timer结合 timeBeginPeriod或System.Windows.Threading.DispatcherTimer是首选。对于测量代码执行时间System.Diagnostics.Stopwatch是当之无愧的最佳和最简单的选择。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询