请注意,我要问的是,使用类似的东西,每隔15毫秒就会调用一次回调函数System.Threading.Timer.我不是在询问如何使用类似System.Diagnostics.Stopwatch甚至是类似的东西准确计算代码QueryPerformanceCounter.
另外,我已经阅读了相关问题:
准确的Windows计时器?System.Timers.Timer()限制为15毫秒
这些都没有为我的问题提供有用的答案.
此外,推荐的MSDN文章" 为Windows实现连续更新,高分辨率时间提供程序"是关于计时而不是提供连续的滴答流.
照这样说...
关于.NET计时器对象有很多不好的信息.例如,System.Timers.Timer被称为"针对服务器应用程序优化的高性能计时器".并且System.Threading.Timer在某种程度上被认为是二等公民.传统的观点认为,System.Threading.Timer是围绕Windows的包装定时器队列定时器,并且System.Timers.Timer完全是另一回事.
现实情况大不相同. System.Timers.Timer只是一个瘦的组件包装器System.Threading.Timer(只需使用Reflector或ILDASM来查看内部System.Timers.Timer,你会看到引用System.Threading.Timer),并有一些代码将提供自动线程同步,所以你不必这样做.
System.Threading.Timer事实证明,它不是 Timer Queue Timers的包装器.至少不在2.0运行时,它是从.NET 2.0到.NET 3.5使用的.使用Shared Source CLI几分钟后,运行时会实现自己的定时器队列,类似于Timer Queue Timers,但实际上从不调用Win32函数.
似乎.NET 4.0运行时还实现了自己的计时器队列.我的测试程序(见下文)在.NET 4.0下提供与.NET 3.5相似的结果.我已经为Timer Queue Timers创建了自己的托管包装器并证明我可以获得1 ms的分辨率(具有相当好的准确性),所以我认为我不太可能错误地读取CLI源代码.
我有两个问题:
首先,是什么原因导致运行时计时器队列的实现如此缓慢?我的分辨率不能超过15毫秒,精度似乎在-1到+30毫秒的范围内.也就是说,如果我要求24毫秒,我会在23到54毫秒之间的任何地方得到滴答声.我想我可以花更多时间使用CLI源来追踪答案,但我想这里有人可能知道.
其次,我意识到这很难回答,为什么不使用定时器队列定时器?我意识到.NET 1.x必须在没有这些API的Win9x上运行,但它们自Windows 2000以来就存在,如果我没记错的话,那就是.NET 2.0的最低要求.是因为CLI必须在非Windows机器上运行吗?
我的计时器测试程序:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
namespace TimerTest
{
class Program
{
const int TickFrequency = 5; …Run Code Online (Sandbox Code Playgroud) 我有一个相对较大的系统(到目前为止约25000行)用于监控无线电相关设备.它使用最新版本的ZedGraph显示图表等.该程序使用Win7上的VS2010上的C#进行编码.问题是:
我希望程序能够快速运行!
解决方案中的每个项目都设置为RELEASE,Debug非托管代码为DISABLED,定义DEBUG和TRACE常量为DISABLED,优化代码 - 我尝试了,警告级别 - 我试过,抑制JIT - 我试过,或者我试过所有StackOverflow上已经提出的解决方案 - 没有成功.程序在分析器外部很慢,在分析器中很快.我不认为问题出在我的代码中,因为如果我将探查器附加到其他不相关的进程中它会变得很快!
请帮忙!我真的需要它在各地快速,因为它是一个关键业务应用程序和性能问题是不能容忍的...
更新1 - 8跟随
-------------------- UPDATE1:--------------------
问题似乎与ZedGraph无关,因为在我用自己的基本绘图替换ZedGraph之后它仍然存在.
-------------------- UPDATE2:--------------------
在虚拟机中运行该程序,该程序仍然运行缓慢,并且从主机运行的探查器不会使它快速.
-------------------- UPDATE3:--------------------
启动屏幕捕获到视频也可以加快程序的速度!
-------------------- UPDATE4:--------------------
如果我打开英特尔图形驱动程序设置窗口(这个东西:http://www.intel.com/support/graphics/sb/img/resolution_new.jpg),只是不断地将光标悬停在按钮上,这样它们就会发光,等等,我的节目加快了!如果我运行GPUz或Kombustor,它不会加速,因此没有GPU上的超频 - 它保持稳定850Mhz.
-------------------- Update5:--------------------
测试不同的机器:
- 在配备Intel HD2000的Core i5-2400S上,UI运行缓慢,CPU使用率约为15%.
- 在配备英特尔G41 Express的同事的Core 2 Duo上,UI运行速度很快,但CPU使用率约为90%(这也不正常)
- 在配备专用Radeon X1650的酷睿i5-2400S上,UI运行速度极快,CPU使用率约为50%.
-------------------- Update6:--------------------
一段代码,显示我如何更新单个图形(graphFFT是ZedGraphControl易于使用的封装):
public void LoopDataRefresh() //executes in a new thread
{
while (true)
{
while (!d.Connected)
Thread.Sleep(1000);
if (IsDisposed)
return; …Run Code Online (Sandbox Code Playgroud) 问题:System.Threading.Timer尽管OS时钟分辨率更精确,
为什么保持15ms的分辨率?在没有繁忙的CPU等待的情况下,实现1ms定时事件分辨率的可行方法是什么?
再次强调:在我的情况下,系统计时器的分辨率为1ms(而不是建议重复的问题).所以这不是系统计时器分辨率的问题.因此,在所谓的重复问题中没有有用的信息.
背景:
.NET似乎System.Threading.Timer 没有使用系统时钟分辨率 - 它保持了~15ms的分辨率.尽管OS时钟(例如Sleep分辨率)更加精确.
在我的盒子上(当几乎空闲且4个核心可用时):
>Clockres.exe
ClockRes v2.0 - View the system clock resolution
Copyright (C) 2009 Mark Russinovich
SysInternals - www.sysinternals.com
Maximum timer interval: 15.625 ms
Minimum timer interval: 0.500 ms
Current timer interval: 1.001 ms
Run Code Online (Sandbox Code Playgroud)
输出我的快速测试:
Sleep test:
Average time delta: 2[ms] (from 993 cases)
System.Threading.Timer test:
Average time delta: 15[ms] (from 985 cases)
Run Code Online (Sandbox Code Playgroud)
测试代码是:
private static void TestSleepVsTimer(long millisecondsDifference, int repetions)
{
TimingEventsKeeper timingEventsKeeper …Run Code Online (Sandbox Code Playgroud) 我正在开发一个分析实时财务数据的应用程序.目前我的主要计算周期有以下设计:
long cycle_counter=0;
while (process_data)
{
(analyse data, issue instruction - 5000 lines of straightforwasrd code with computations)
cycle_counter++;
Thread.Sleep(5);
}
Run Code Online (Sandbox Code Playgroud)
当我在我的笔记本(一个Core i5)处理器上运行这个应用程序时,循环每秒运行200-205次 - 这是一种预期的(如果你不打扰为什么它每秒运行超过200次).
但是,当我在具有2个6核Xeon处理器和24 GB快速RAM的"真实"工作站上部署应用程序,并在大约3秒钟内加载Win7时,应用程序每秒运行大约67次.
我的问题是:
为什么会这样?
在这种情况下,如何影响每秒的运行次数?
有没有更好的解决方案,每秒运行200-1000次循环?我现在正在考虑删除Thread.Sleep()(我在这里使用它的方式受到了很多批评).有12个内核,我只使用一个内核就可以解决这个问题.但是我的解决方案有一些缺点吗?
谢谢你的想法.