毫秒级的定时器控件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了毫秒级的定时器控件相关的知识,希望对你有一定的参考价值。

vc++的settimer只能精确到55ms左右的定时,请问有没精确到1ms的控件或方法。能够使它在::OnTimer(UINT nIDEvent)定时1ms进行编程?
不够分再加。
能不能举个具体点的例子呢,先定时1ms,然后在::OnTimer(UINT nIDEvent)里编写事件,实现每1ms做一件事。满足要求我加100分。谢谢了。
你的程序可以运行,但我要怎么在对话框里调用,void CALLBACK mycallback (UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) 应该怎么改,MMRESULT mr = timeSetEvent( 10/*毫秒数*/, 1000, mycallback,0,TIME_PERIODIC);
这句我放在按钮事件里了。

必须使用多媒体定时器

基于WM_TIMER消息的定时器是低精度的,它最多可以精确到54.915毫秒,大约每秒18.2次,并且WM_TIMER消息的优先级比较低,它可能造成WM_TIMER消息的"丢失",从精度和优先级的考虑,在本例中不能使用该定时器完成任务,因此我用到了Windows多媒体服务中提供的多媒体定时器。

1. 确定最大和最小周期
可以用timeGetDevCaps函数确定定时器服务提供的最大和最小定时器事件周期,这些数值对不同的计算机是变化的,也与Windows运行方式有关。
2. 建立最小时间精度
在启动定时器事件前,应用程序必须建立想要使用的最小定时器精度,在定时器服务事件结束之后,必须清除该精度。用户可以使用timeBeginPeriod和timeEndPeriod函数来设置和清除最小定时器精度,每个timeBeginPeriod调用都必须有一个timeEndPeriod与之对应,且两个函数必须指定相同的最小精度。
3. 启动定时器事件
与该步骤相关的两个函数为timeSetEvent和timeKillEvent,读者可以查阅这两个函数,有两个值得注意的地方:一是启动定时器事件就一定要把它清除,因为小于100ms 的定时器对CPU 的消耗是非常大的;二是在timeSetEvent调用中设置定时器回调函数时要遵循其规则。读者可以参考下面的例程。

三、 例程

本例程提供了串口类(CCOM)和多媒体定时器操作类(CMMTimer)的完整代码,有兴趣的读者可以直接把它们应用于您的程序中。

//COM.h
class CCOM

public:
CCOM();
virtual ~CCOM();

BOOL InitCOM();
BOOL SendCOMCode(unsigned _int8 chCode[], int nNum);
DWORD GetCOMData(unsigned char *pchBuffer);
void CloseCOM();

HANDLE hCOM;
;

//COM.cpp
CCOM::CCOM()



CCOM::~CCOM()



BOOL CCOM::InitCOM()//初始化串口

DCB dCB;
COMMTIMEOUTS ct;

//得到打开串口,并得到串口句柄
hCOM = CreateFile( "COM1", GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if(hCOM == INVALID_HANDLE_VALUE)
return FALSE;

//初始化串口,READBUFFER和WRITEBUFFER是用户自己定义的两个宏
SetupComm(hCOM, READBUFFER, WRITEBUFFER);
PurgeComm(hCOM, PURGE_TXCLEAR|PURGE_RXCLEAR);

//设置DCB结构
if(!GetCommState(hCOM, &dCB))

CloseHandle(hCOM);
return FALSE;

dCB.BaudRate = 38400;
dCB.ByteSize = 8;
dCB.Parity = NOPARITY;
dCB.StopBits = ONESTOPBIT;
if(!SetCommState(hCOM, &dCB))

CloseHandle(hCOM);
return FALSE;


//设置超时值
ct.ReadIntervalTimeout = MAXDWORD;
ct.ReadTotalTimeoutConstant = 0;
ct.ReadTotalTimeoutMultiplier = 0;
ct.WriteTotalTimeoutConstant = 0;
ct.WriteTotalTimeoutMultiplier = 0;
if(!SetCommTimeouts(hCOM, &ct))

CloseHandle(hCOM);
return FALSE;

return TRUE;


BOOL CCOM::SendCOMCode(unsigned _int8 chCode[], int nNum)//写串口

DWORD dwWritenNum;
return WriteFile(hCOM, chCode, nNum, &dwWritenNum, NULL);


DWORD CCOM::GetCOMData(unsigned char *pchBuffer)//读串口

DWORD dwReadNum;
ReadFile(hCOM, pchBuffer, READBUFFER, &dwReadNum, NULL);
return dwReadNum;


void CCOM::CloseCOM()

CloseHandle(hCOM);


//MMTimer.h
class CMMTimer

public:
CMMTimer();
virtual ~CMMTimer();

BOOL SetMMTimer(UINT nInterval, UINT nResolution);
void KillMMTimer();
UINT nTimerRes, nTimerID;
;

//MMTimer.cpp
//回调函数声明
void PASCAL MMTimerProc(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1,
DWORD dw2);

CMMTimer::CMMTimer()



CMMTimer::~CMMTimer()



BOOL CMMTimer::SetMMTimer(UINT nInterval, UINT nResolution)// 装载多媒体时钟

//得到定时器精度
TIMECAPS tc;
nTimerRes = nResolution;
if (timeGetDevCaps(&tc, sizeof(TIMECAPS))==TIMERR_NOERROR)

if(nTimerRes!=min(max(tc.wPeriodMin, nTimerRes), tc.wPeriodMax))
return FALSE;


if(timeBeginPeriod(nTimerRes)==TIMERR_NOERROR)//启动定时器精度

nTimerID = timeSetEvent(nInterval, nTimerRes, MMTimerProc, NULL,
TIME_PERIODIC);//启动定时器
if(!nTimerID)
return TRUE;
else
return FALSE;

else
return FALSE;


void CMMTimer::KillMMTimer()//卸载多媒体时钟

if(nTimerID)

timeKillEvent(nTimerID);
nTimerID = 0;

timeEndPeriod(nTimerRes);

void PASCAL MMTimerProc(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1,
DWORD dw2)

//在该例中为读串口数据,您可替换为您的多媒体时钟任务
static unsigned char chData[READBUFFER];
static DWORD dwNum;
dwNum = c_com.GetCOMData(chData);//串口读数
参考技术A Win32 API函数库中已经为用户提供了一组用于高精度计时的底层函数,如果用户使用得当,计时精度可到1ms。这个计时精度,对于一般的实时系统控制完全可以满足要求。现将由BCB提供的重新封装后的一组与时间相关的主要接口函数(函数名、参数、功能与Win32API基本相同)说明如下:

1.DWORD timeGetTime(void)

返回从Windows启动开始经过的毫秒数。最大值为2的32次方,约49.71天。

2.MMRESULT timeSetEvent(UINT uDelay,UINT uResolution,LPTIMECALLBACK
lpTimeProc,DWORD dwUser,UINTfuEvent)

该函数设置一个定时回调事件,此事件可以是一个一次性事件或周期性事件。事件一旦被激活,便调用指定的回调函数,成功后返回事件的标识代码,否则返回NULL.参数说明如下:

uDelay:以毫秒制定事件的周期。

UResolution:以毫秒指定延时的精度,数值越小定时器事件分辩率越高。缺省值为1ms.

LpTimeProc:指向一个回调函数。

DwUser:存放用户提供的回调数据。

FuEvent:指定定时器事件类型:TIME_ONESHOT:uDelay毫秒后只产生一次事件。

TIME_PERIODIC:每隔uDelay毫秒周期性地产生事件。

3.MMRESULT timeKillEvent(UINT uTimerID)

该函数取消一个指定的定时器回调事件。uTimerID标识要取消的事件(由timeSetEvent函数返回的标识符)。如果定时器时间不存在则返回 MMSYSERR_INVALPARAM。

void CALLBACK TimeProc(UINT uID,UINT uMsg,DWORD dwUser,DWORD dw1,DWORD dw2);

该函数是一个应用程序定义的回调函数,出现定时器事件时该函数被调用。TimeProc是应用程序定义的函数名的占位符。使用该函数时要注意的是,它只能调用以下有限的几组API函数:PostMessage,
timeGetSystemTime, timeGetTime, timeSetEvent, timeKillEvent, midiOutShortMsg,
midiOutLongMsg, OutputDebugString。同时也不要使用完成时间很长的API函数,程序尽可能简短。

使用以上一组函数就可以完成毫秒级精度的计时和控制(在BCB使用时要将头文件mmsystem.h加到程序中)。由于将定时控制精确到几毫秒,定时器事件将占用大量的CPU时间和系统资源,所以在满足控制要求的前提下,应尽量将参数uResolution的数值增大。而且定时器实时控制功能完成后要尽快释放。

回复:

# include <stdio.h>
#include "windows.h"
#include "mmsystem.h"

#pragma comment( lib, "Winmm.lib" )

void CALLBACK mycallback (UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)

printf( "Hello" );


void main()


MMRESULT mr = timeSetEvent( 10/*毫秒数*/, 1000, mycallback,0,TIME_PERIODIC);

getchar();

本回答被提问者采纳

Python基础篇:某宝一键秒杀,毫秒级的精准度

某宝秒杀,用毫秒级的精准度来抢购!

前言

还记得前段时间情人节,各种产品活动秒杀。结果有对象的辣条自然少不了被对象一番折磨 (注意:不是new出来的哈,也不是橡胶的,实实在在的女朋友) 于是乎彻底激发了我的求生欲,在这种关头我是必须发挥出自己的才能了,这才有了这篇毫秒级秒杀的精品出来,话不多说直接进入主题

目录

​ 1,项目环境

​ 2,某宝抢购流程分析

​ 3,程序实现思路

​ 4,代码实践与梳理

项目环境

​ 操作系统:Windows 10

​ 开发环境:python3.7

​ IDE:Pycharm

​ 自动化模块:Selenium

​ 安装命令:pip install selenium

​ 浏览器版本:Google Chrome 99.0.4844.51

​ 浏览器驱动版本:ChromeDriver 99.0.4844.51

​ 浏览器驱动版本与浏览器版本要一致!

某宝抢购流程分析

​ 1,登录网站

​ 2,购物车选中抢购商品

​ 3,结算购买

​ 4,提交订单

​ 关键:快速完成前面流程,当订单进入提交页面时,付款时间不影响抢购。

程序实现思路

​ 购物流程都是固定没有变化的,因此可以把购物流程步骤用代码编辑好交给selenium去自动执行。

​ 项目结构:驱动直接复制放入项目根路径

1,导入对应类库实现对浏览器的操作
# author:辣条
# ide: PyCharm

from selenium import webdriver
import datetime	
import time

#自动打开浏览器并且最大化窗口
driver = webdriver.Chrome()
driver.maximize_window()

​ 执行上述代码,浏览器会自动打开并显示如下,证明我们已经开始通过代码操控浏览器了。

2,用代码实现购物流程
2.1 访问某宝:
driver.get('https://www.taobao.com')
2.2登录某宝:

if driver.find_element_by_partial_link_text('亲,请登录'):
        driver.find_element_by_partial_link_text('亲,请登录').click()
2.3 进入购物车
#跳转到购物车页面
driver.get('https://cart.taobao.com/cart.htm')
2.4 选中所有商品

#寻找全选选项并勾选
if driver.find_element_by_id("J_SelectAll1"):
      driver.find_element_by_id("J_SelectAll1").click()
2.5 对比时间,提交结算(重点)
def buy(buy_time):  #buy_time 购买时间
    while True:
        now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
        print('当前时间:%s'%now)

        #判断是否到达抢购时间
        if now>buy_time:
            try:
                driver.find_element_by_partial_link_text('结 算').click()
            except:
                pass
		#对比时间,循环提交订单
        while True:
                try:
                    if driver.find_element_by_link_text('提交订单'):
                        driver.find_element_by_link_text('提交订单').click()
                        print(f"抢购成功,请尽快付款")
                except:
                    print(f"再次尝试提交订单")
            time.sleep(0.01)

这样就可以通过设定的段时间去定时定点抢购商品啦!

    print(f"再次尝试提交订单")
        time.sleep(0.01)

[外链图片转存中...(img-oA7Q06eg-1648366756452)]

​	**这样就可以通过设定的段时间去定时定点抢购商品啦!**

以上是关于毫秒级的定时器控件的主要内容,如果未能解决你的问题,请参考以下文章

毫秒级定时任务定时执行定时任务执行软件 —— 定时执行专家

VB定时器控件Interval属性设置为0是啥意思?

winform 中如何获取计时器控件的值

C#定时器控件Timer

定时器软件如何制作?Delphi

C#关于定时器和多线程中对控件的操作以及界面假死的现象。