相关疑难解决方法(0)

为什么.NET计时器的分辨率限制在15毫秒?

请注意,我要问的是,使用类似的东西,每隔15毫秒就会调用一次回调函数System.Threading.Timer.我不是在询问如何使用类似System.Diagnostics.Stopwatch甚至是类似的东西准确计算代码QueryPerformanceCounter.

另外,我已经阅读了相关问题:

准确的Windows计时器?System.Timers.Timer()限制为15毫秒

.NET中的高分辨率计时器

这些都没有为我的问题提供有用的答案.

此外,推荐的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)

.net timer

61
推荐指数
2
解决办法
3万
查看次数

System.Timers.Timer仅提供每秒最多64帧

我有一个应用程序,它使用System.Timers.Timer对象来引发由主窗体(Windows窗体,C#)处理的事件.我的问题是,无论我设置.Interval(甚至1毫秒)有多短,我每秒最多得64次.

我知道Forms计时器的精度限制为55毫秒,但这是System.Timer变体,而不是Forms表单.

该应用程序占用1%的CPU,因此它绝对不受CPU限制.所以它所做的只是:

  • 将Timer设置为1&nsp; ms
  • 触发事件时,增加_Count变量
  • 再次将其设置为1&nsp; ms并重复

即使没有其他工作要做,_Count每秒最多增加64次.

这是一个"回放"应用程序,它必须复制进来的数据包,它们之间只有1-2毫秒的延迟,所以我需要能够每秒可靠地发射1000次的东西(尽管如果我能满足100的话)是CPU限制的,我不是).

有什么想法吗?

.net c# timer winforms

11
推荐指数
1
解决办法
1697
查看次数

使用timeBeginPeriod /任务调度时Thread.Sleep与Task.Delay

给出附加的LINQ-Pad片段.

它创建8个任务,执行500毫秒并绘制线程实际运行时的图表.

在4核CPU上,它可能如下所示: 在此输入图像描述

现在,如果我在线程循环中添加Thread.Sleep Task.Delay,我可以看到windows系统计时器的时钟(~15ms):

在此输入图像描述

现在,还有一个timeBeginPeriod功能,我可以降低系统计时器的分辨率(在例子中为1ms).这就是区别.随着Thread.Sleep我得到这个图表(我的预期):

在此输入图像描述

使用时,Task.Delay我获得与时间设置为15ms时相同的图形:

在此输入图像描述

问题:为什么TPL忽略了定时器设置?

这是代码(你需要LinqPad 5.28 beta运行图表)

void Main()
{
    const int Threads = 8;
    const int MaxTask = 20;
    const int RuntimeMillis = 500;
    const int Granularity = 10;

    ThreadPool.SetMinThreads(MaxTask, MaxTask);
    ThreadPool.SetMaxThreads(MaxTask, MaxTask);

    var series = new bool[Threads][];
    series.Initialize(i => new bool[RuntimeMillis * Granularity]);

    Watch.Start();
    var tasks = Async.Tasks(Threads, i => ThreadFunc(series[i], pool));
    tasks.Wait();

    series.ForAll((x, y) => series[y][x] ? new { X = x / (double)Granularity, Y …
Run Code Online (Sandbox Code Playgroud)

c# multithreading task-parallel-library

4
推荐指数
1
解决办法
587
查看次数