关于如何确保一个成员函数每隔一定时间就执行一次的问题,这个不是简单的SetTimer问题。
需求是这样的:    1.程序要求每隔15秒读取一次数据。实际是该时间间隔必须在10秒与20秒之间,取了中间的15;
    2.将读取的数据写入新文件中,并根据读取的时间作为文件名。将该文件名保存到表中,用于在步骤3中调用;
    3.从表中读取新生成的数据文件名称,打开文件,将该文件内容按一定的规则进行处理。    以上1、2、3是完成一次处理所需的流程顺序。要求对读取到的数据的后续的处理不能影响每隔15秒读一次数据,也就是说,无论后续数据处理怎么耗时,都必须确保每隔15秒读取一次数据,最迟不能超过20秒(15秒内肯定能把数据读完并保存到新文件中,这不是问题)。
    关键是第三步对新文件的处理非常复杂,是个while循环,导致非常耗时。请朋友们不要关注怎样改进文件处理规则来提高处理时间,规则是固定的,不能改,每次处理至少5分钟才能完成。所以问题由此而来,怎么样让数据处理不干扰数据读取,也就是说把这两个过程独立起来,各执行各的。已采取的方案有:
    方案1:使用计时器。创建两个计时器,计时器1用于读数据,时间间隔为15秒;计时器2用于处理数据,时间间隔为7分钟。
    该方案的问题是当处理数据时while循环会导致程序的窗口点击无法响应,象死机一样,同样也导致计时器1发出的WM_TIMER消息被阻塞,即整个处理数据期间根本无法读取数据,导致读取数据严重超时。    方案2:只创建一个计时器,用于处理数据。而读取数据则使用COleDateTime类与COleDateTimeSpan类结合while循环来计时。例如: while(bIsOK) //bIsOK用于控制循环退出
{
//设定循环时间间隔为15秒
int nInterval = 15
//开始时间,用于计算延时
COleDateTime tStart = COleDateTime::GetCurrentTime(); //开始读数据
ReadData(); //计算耗时
COleDateTimeSpan tsSecond = COleDateTime::GetCurrentTime() - tStart;
int nSeconds = tsSecond.GetTotalSeconds();
//开始延时。只要从读数据开始到现在未达到15秒就延时,直到达到15秒再退出延时,
while(bIsOK && nSeconds < nInterval)
{
//计算剩余的延迟时间
tsSecond = COleDateTime::GetCurrentTime() - tStart;
nSeconds = tsSecond.GetTotalSeconds();
//每2秒进行一次消息循环,否则窗口无法响应用户操作。
if(nSeconds%2 == 0 && ::GetMessage(&msg,NULL,0,0))
{
::TranslateMessage(&msg); 
::DispatchMessage(&msg);
}
}
}
    该方案的问题是:因为在延时中加入了消息处理,而有的消息处理会耗费时间,所以延时经常不准确。不加消息处理时延时是非常精确的,但不加消息处理时程序窗口无法响应,象死机了一样。问题就是这样了,请朋友们帮忙解决一下。尽量不要创建线程以在线程中进行数据处理。我希望能使用一种办法确保无论系统多么繁忙或被阻塞,总能保证每隔15秒执行一次读数据的成员函数。

解决方案 »

  1.   

    使用多线程,这个难题就不难了
    难道没制定这个方案?别执着MFC,消息机制
      

  2.   

    方案2可以解决问题啊,延时虽然不准确,但应该不会超过20秒吧,实在不行可以把nInterval改小点如果不引入多线程就只能这样了,而且就算引入多线程也不能做到完全精确,因为windows毕竟不是实时操作系统
      

  3.   

    必须多线程吧
    楼主的文件操作的耗时是不确定的
    timer肯定准不了
      

  4.   

    你这个应该用简单的多线程技术应该就可以了吧!
    下面是多线程简单用例,你看一下,不难!
    http://download.csdn.net/source/1123495
    当然,多线程用的复杂了,还是比较难的!
      

  5.   

    等待定时器内核对象
    CreateWaitableTimer
    SetWaitableTimer
      

  6.   

    谢谢这位朋友提供的CreateWaitableTimer,暂时没有采用,以后会好好研究一下。
    感谢参与的各位热心的朋友们!
    另外,要特别感谢一下钻石cnzdgs,您的参与让这个帖子蓬荜生辉!
      

  7.   

    来晚了。。学习顶。up..up我正在使用《Csdn收音机》第一时间获取最新动态!