计时器运行的原理与大量计时器不同步问题

时间:2022-08-15 20:35:44
一个主计时器控制3个子计时器,interval均为100ms,目标是按循序print 1,2,3
点击command1后,下列代码的结果是print:2,1,3   显然不是自己想要的。

1.如果将横线处sleep 100 改为sleep 200 则正常print 1,2,3。

2.如果均不加延时,则完全随机print

  在编写程序中经常需要用到大量计时器,因而也经常出现奇奇怪怪的不同步问题,总而言之,还是对timer的运行原理理解不够。

  个人主观的认为:
  1.不涉及外部计时器的内部指令是从上到下执行的,
  2.而控制外部计时器时,则与外部计时器间隔有关,有时同步有时不同步。

恳请高手释疑

Private Sub Command1_Click()
   Timer.Enabled = True
End Sub

Private Sub Timer_Timer()   
   Timer1.Enabled = True

   DoEvents
   Sleep 100        ---------------------------------------
            

   Timer2.Enabled = True
   
   DoEvents
   Sleep 100  
   
   Timer3.Enabled = True

   Timer.Enabled = False
End Sub


Private Sub Timer1_Timer()
 Print "1"
 Timer1.Enabled = False
End Sub

Private Sub Timer2_Timer()
 Print "2"
 Timer2.Enabled = False
End Sub

Private Sub Timer3_Timer()
 Print "3"
 Timer3.Enabled = False
End Sub

66 个解决方案

#1


建议仅使用一个Timer,在该Timer中使用状态机的思路控制执行所需程序段。
参考《编译原理》词法分析 有限状态自动机

#2


有限状态自动机看不懂啊。
俺是新手,希望能从计时器运行原理上来找到问题所在,网上找了很多,但是都没有对计时器控件的深入分析。

有没有比较简单明了的解释来说明上述问题的症结所在? 万分感谢

#3


有限状态自动机举例:
//有字符串
//1_22_333,,4444__55555,_666666
//需要解析为
//1
//22
//333
//_
//4444
//55555
//666666
#include <stdio.h>
char s[]="1_22_333,,4444__55555,_666666";
char c,*p,*p1;
int st;
void main() {
    st=0;
    p=s;
    while (1) {
        c=*p;
        if (0==c) {
            switch (st) {
            case 1:printf("_\n");    break;
            case 2:printf("%s\n",p1);break;
            }
            break;//
        }
        switch (st) {
        case 0:
                 if ('_'==c) {                            st=0;}
            else if (','==c) {                            st=1;}
            else             {p1=p;                       st=2;}
        break;
        case 1:
                 if ('_'==c) {                            st=1;}
            else if (','==c) {printf("_\n");              st=1;}
            else             {p1=p;                       st=2;}
        break;
        case 2:
                 if ('_'==c) {*p=0;printf("%s\n",p1);*p=c;st=0;}
            else if (','==c) {*p=0;printf("%s\n",p1);*p=c;st=1;}
            else             {                            st=2;}
        break;
        }
        p++;
    }
}
//1
//22
//333
//_
//4444
//55555
//666666

#4


不要在程序里面多多个计时器, 也不要在定时器里面自己关掉自己这种动作.

一个计时器就够了, 就像你的手机上可以设置多个闹钟一样, 一个手机一个闹钟那不得烦死? 

效率低, 管理也成问题.

#5


不要在程序里面多多个计时器, 也不要在定时器里面自己关掉自己这种动作.

一个计时器就够了, 就像你的手机上可以设置多个闹钟一样, 一个手机一个闹钟那不得烦死? 

效率低, 管理也成问题.

#6


目前设计的是全自动交易软件, 全天反复进行双向指令交易,最大一天可交易60余笔,一般情况下不会出问题,但有时会出现BUG。首先肯定是计时器的问题。

根据价格的不断变动,实时发送指令,如果不采用大量计时器控制,如何实现自动化??

实际上,虽然采用了数十个计时器,但是实际上只有1-2个计时器在运行。

因为对计时器的原理了解不够,所以才有上述之问。

#7


1)计时器使用时概念上就应该认为是相互独立的,计时器的前后差异会引起BUG,那说明还需要解耦。
2)DoEvents能不用尽量不要用,那是灾难。
3)chrome浏览器开着的时候会对计时器的计时精度产生影响
4)交易这种东西时间精度不该需要太高的,如果时间精度真的要求比较高的话,VB其实是不合适的。

#8


用一个定时器,一次只执行一次交易。
Option Explicit

Private Const TASK_COUNT As Long = 3
Private m_TaskIndex As Long
Private m_aTaskEnabled(0 To TASK_COUNT - 1) As Boolean

Private Sub Command1_Click()
    '设置各交易的活跃状况'
    m_aTaskEnabled(0) = True
    m_aTaskEnabled(1) = False
    m_aTaskEnabled(2) = True
    m_TaskIndex = 0
    
    Timer1.Interval = 100
    Timer1.Enabled = True
End Sub

Private Sub Timer1_Timer()
    Dim i As Long
    Dim lCount As Long
    
    '找到下一个活跃的交易'
    i = m_TaskIndex
    lCount = 0
    Do While lCount < TASK_COUNT
        If m_aTaskEnabled(i) Then Exit Do
    
        i = (i + 1) Mod TASK_COUNT
        lCount = lCount + 1
    Loop
    
    If lCount = TASK_COUNT Then
        Print "没有交易"
    Else
        m_TaskIndex = (i + 1) Mod TASK_COUNT
        Print "交易" & CStr(i + 1)
    End If
End Sub

#9


给段多单的代码,空单也一样:
'************///多单进出场主控制器'buymain计时器逐级控制进场,与buystopmain控制出场

Private Sub BuyMainTimer_Timer()  
 If BuyAimClass <> 11 Then  
  Dim i As Integer
  For i = 1 To 10 
    Me.Controls("BuyTimer" & i).Enabled = False  'BuyTimer
  Next
  
  DoEvents
  Sleep 100
  
  Me.Controls("BuyTimer" & BuyAimClass).Enabled = True
  BuyMainTimer.Enabled = False '
End If
End Sub


Private Sub BuyStopMainTimer_Timer() 
  Dim i As Integer
   For i = 1 To 4
     Me.Controls("BuyStopTimer" & i).Enabled = False
   Next
   
   DoEvents
   Sleep 100
   
   Me.Controls("BuyStopTimer" & BuyHoldClass).Enabled = True
   BuyStopMainTimer.Enabled = False '自关闭
End Sub

Private Sub BuyStopTimer1_Timer()
  If BuyHoldClass = 1 Then
    If Buy1P <= BuyBaseP + N * (BuyAimClass - 1) - N * 2 Then  
     
       MaiChuP Volume * 1, L_Stop
              
       BuyAimClass = BuyAimClass - 1
       BuyHoldClass = 0
       BuyMainTimer.Enabled = True
       
       BuyStopTimer1.Enabled = False '自关闭
    End If
  End If
End Sub




Private Sub BuyTimer1_Timer()
  If Sell1P >= BuyBaseP + N Then       '当价格达到1级目标价格时
   
     DoEvents
     Sleep 100  '保证先平后开   

    MaiRuK Volume, U_Stop

    BuyHoldClass = BuyHoldClass + 1
    BuyAimClass = BuyAimClass + 1
    
BuyMainTimer.Enabled = True 
    BuyStopMainTimer.Enabled = True '持仓后启动止损,无持仓不启动止损
    
    BuyTimer1.Enabled = False  '关闭本计时器

#10


可以随时更改 m_aTaskEnabled(i) 的状态,达到启动/关闭的目的。

#11


每个Timer事件里都有
DoEvents
 Sleep 100
这两行,这是干嘛?

还有,BuyMainTimer.Enabled = False之类的要放在doevents前边,不要放在后边,不然会有事件重入的问题.

#12


另外你可以用Timer数组来代替现在这些,至少名字上可以省心很多

#13


引用 11 楼 bakw 的回复:
每个Timer事件里都有
DoEvents
 Sleep 100
这两行,这是干嘛?

还有,BuyMainTimer.Enabled = False之类的要放在doevents前边,不要放在后边,不然会有事件重入的问题.



1.保证先后顺序。先全部关闭子计时器,后启动对应子计时器,防止走势过快时已启动的子计时器先触发,之后又通过maintimer启动同一个计时器导致重复错误的产生。
2.因为双向监控大量计时器,当多空交换时,若同时触发平仓和开仓,此时将只有一个指令被执行,另一个将失效。在开仓中延时100ms,保证先平后开,避免指令失效问题产生

#14


 1.请教bakw:事件重入是什么情况?

2.后来发现一个问题,因为我在另一个独立运行的计时器(间隔15s)中加入了sleep 1000,假如buytimer1此时刚好触发并进入倒计时,则立即被中断,中断结束后,buytimer1中代码因为尚未执行关闭buytimer1,导致buytimer1又执行一个间隔,相当于同时执行了2次buytimer1,而一旦buytimer1刚刚进入倒计时此时再触发buytimer1将导致完全重复的问题产生。
  不知道我对这个问题的解释对不对?

3.关于timer计时器控制外部计时器timer1的问题:应当是先执行内部指令,之后外部计时器的执行是根据其interval倒计时执行的,因此(举个例子):无论timer中print "hello" 写在timer.enabled=false timer1.enabled=true  前还是后,都先执行print "hello"。关闭自身应也是一样,在执行完timer代码后,隔一个interval才会关闭timer
   

#15


不太理解流程,不过感觉定时器这种用法应该是有问题的
重入的话,比如timer定时是100ms一次的,但timer_timer事件中代码执行时间超过了100ms,这个时候另一个timer_timer事件在doevents调用结束之前又产生了.

#16


引用 15 楼 bakw 的回复:
不太理解流程,不过感觉定时器这种用法应该是有问题的
重入的话,比如timer定时是100ms一次的,但timer_timer事件中代码执行时间超过了100ms,这个时候另一个timer_timer事件在doevents调用结束之前又产生了.


你说的很有道理。
对于重入,查了些资料有些认为会重入,有些认为不会重入。不管重入不重入,刚才测试了以下timer中代码执行的时间基本为0,因此也不会产生重入问题。

在对timer没有深入了解之前就直接进行大量计时器交替控制操作,因此产生了这样那样奇怪的不同步问题。比如原来觉得代码是顺序执行的,没有考虑到间隔问题,以为timer1.enabled=true (false)后timer2.enabled=true (false)就先启动timer1后启动2,后来才发现不是这样的。

我是VB新手,平常上班较忙,因此2个月的时间编了一个外挂专门用于15秒-1分钟级期货自动交易策略测试,点击启动后一整天就不用再管了,程序自动发送交易指令,目前基本运行稳定,但是不时有各种bug出现。今天测试了一整天,才基本找到一个问题的原因,已经改好了,但效果仍需测试,新的问题仍旧有可能发生。

大量timer确实不好控制,有一点没有照顾到就容易不按设计出牌,需要深入了解其脾性。现在主要采用的是交替控制,触发条件即关闭并通过主控重新选择新的计时器。


对于timer控件的原理还有不少疑惑,不知哪里有比较深入详细的学习资料,msdn已经看过了。


#17


重入会导致程序无法正常退出,需要用End强行退出,我写过几个通讯程序,因为在通讯等待的时候用了doevents就造成这样的后果:在doevents的时候执行了unload退出,等从doevents返回的时候,对象已经被卸载了,结果程序又不得不重建一个实例,好让doevents有地方可以返回,但这个时候,所有的状态变量已经被清空了,所以程序又无法知道,在doevents里的时候其实已经是执行了退出的。于是变成了一个退不掉的后台程序。
详细资料没有看到过,VB是单线程的程序,尽可能从这个角度去理解Timer会好一些.

#18


你的程序用法,类似于把定时器当成线程,可惜VB是单线程的,一个确定时刻程序只处于一个确定的位置。

#19


该回复于2015-01-02 11:09:52被管理员删除

#20


感觉好复杂的样子~

#21


计算可以开线程,VB可以用API开线程
1)定时器不要做太多的工作,否则会有积压
2)定时器不要Sleep,Sleep 会造成定时器积压 
积压的定时器,会造成界面和其他操作延迟

定时的时间间隔不要太小,虽然定时器,代码简短时候,可以保证
 时间间隔小的操作,平均时间间隔的得到保证
但是会瞬间连续启动n 次定时器,不是你想要的

定时器的界面操作也不宜太多,更多的界面操作,还是交给事件处理
PS:
定时器不宜太多

#22


定时器的原理,
是利用硬件定时器中断程序的时机,
安排一段独立的代码,
该代码利用线程的时间片,
和线程分时并行运行,
可以看作作线程的一个分支程序,
----------线程正常运行时候,只有一条运行路线,开定时器有两天运行路线---------


#23


学习了,加油楼煮

#24


计时器运行的原理与大量计时器不同步问题

#25


不错,收藏下 计时器运行的原理与大量计时器不同步问题

#26


感觉好复杂的样子~

#27


好的,不错,给力

#28


好多大神……………………………………………………………………

#29


计时器运行的原理与大量计时器不同步问题

#30


learning

#31


沙发一个 计时器运行的原理与大量计时器不同步问题

#32


vb不能多线程,用vb.net吧。我的自动化交易用两个线程解决,一个接受行情,一个计算并交易。

#33


mark 计时器运行的原理与大量计时器不同步问题

#34


引用 22 楼 lm_whales 的回复:
定时器的原理,
是利用硬件定时器中断程序的时机,
安排一段独立的代码,
该代码利用线程的时间片,
和线程分时并行运行,
可以看作作线程的一个分支程序,
----------线程正常运行时候,只有一条运行路线,开定时器有两天运行路线---------

计时器运行的原理与大量计时器不同步问题

#35


该回复于2015-01-03 17:25:00被管理员删除

#36


该回复于2015-01-04 10:08:53被管理员删除

#37


讨论得太高深了,根本看不懂,不过把楼主的程序复制运行一下,结果与讨论所确定的命题有所不同,但确满足楼主的需求,好奇了...

#38


想上传一个20K的截图,点上传,在那儿转了十几分钟圈子,CSDN 消亡恐怕快了.

#39


计时器运行的原理与大量计时器不同步问题

#40


厉害,学习到很多

#41


想上传一个20K的截图,点上传,在那儿转了十几分钟圈子,CSDN 消亡恐怕快了

#42


计时器同步有时是特别重要的问题

#43


该回复于2015-01-05 10:02:10被管理员删除

#44


该回复于2015-01-05 10:03:33被管理员删除

#45


多定时器完全是设计错误,按我#8的例子用单个定时器就能实现的。
楼主你想太多了!

#46


感觉好复杂,学习了~

#47


理论上来说三个计时器干的活,应该是相应没有影响,没有任何关系的。
如果有关系或是有先后顺序,应该是一个计时器来控置。
或者是一个计时器完了,再调下一个计时器。

#48


提醒:处理不过来时需要使用FIFO队列保存请求和结果,并监视FIFO队列防止溢出。

#49


引用 21 楼 lm_whales 的回复:
计算可以开线程,VB可以用API开线程
1)定时器不要做太多的工作,否则会有积压
2)定时器不要Sleep,Sleep 会造成定时器积压 
积压的定时器,会造成界面和其他操作延迟

定时的时间间隔不要太小,虽然定时器,代码简短时候,可以保证
 时间间隔小的操作,平均时间间隔的得到保证
但是会瞬间连续启动n 次定时器,不是你想要的

定时器的界面操作也不宜太多,更多的界面操作,还是交给事件处理
PS:
定时器不宜太多



实际上最多的时候一次使用了120个计时器,但是由于交替控制,因此一次只有不超过3个计时器在运行,其他计时器全部处于关闭状态。
您说的sleep问题确实存在,后来专门进行了测试:两个计时器,一个间隔(1000ms)代码为sleep 1000,另一个间隔(2000ms)代码为print "hello"并获取执行代码的毫秒级时间,结果是print"hello"发生在3000ms之后,有时发生在1000ms后


我现在又遇到一个问题:buystopmaintimer为主控,buystoptimer1为子控  interval全为100ms,代码如下。正常情况下应该是buystoptimer1触发后自行关闭不会被触发,但是在实际运行过程中,偶尔会出现重复发送代码指令的问题。(备注:产生问题的可能原因:第三方计时器中有一次doevents sleep 50的代码,若同时触发可能产生这个问题,但是按照我在上述的测试,sleep后被中断倒计时的buystoptimer1r应当会继续执行代码而不是又执行一个间隔)

Private Sub BuyStopMainTimer_Timer() 
   Dim i As Integer
   For i = 1 To 4
     Me.Controls("BuyStopTimer" & i).Enabled = False
   Next
   
   DoEvents
   Sleep 50
   
   Me.Controls("BuyStopTimer" & BuyHoldClass).Enabled = True
   BuyStopMainTimer.Enabled = False '自关闭
End Sub

Private Sub BuyStopTimer1_Timer()
  If BuyHoldClass = 1 Then
    If Buy1P <= BuyBaseP + N * (BuyAimClass - 1) - N * 2 Then 
       
       MaiChuP Volume * 1, L_Stop
                                 
       BuyAimClass = BuyAimClass - 1        
       BuyHoldClass = 0         
           
       BuyTimer2.Enabled = False         
       BuyStopTimer1.Enabled = False '自关闭
    End If
  End If

#50


引用 32 楼 u011326712 的回复:
vb不能多线程,用vb.net吧。我的自动化交易用两个线程解决,一个接受行情,一个计算并交易。


计时器运行的原理与大量计时器不同步问题

俺现在用的程序框架是用三个计时器同时运行,一个计时器获取行情,一个计时器连接数据库计算均线,一个计时器作为进出场主控制器。 我是新手,大学学过一点vb,就用6.0编了一个,线程问题还是最近才了解。很有用的参考,谢谢!

#1


建议仅使用一个Timer,在该Timer中使用状态机的思路控制执行所需程序段。
参考《编译原理》词法分析 有限状态自动机

#2


有限状态自动机看不懂啊。
俺是新手,希望能从计时器运行原理上来找到问题所在,网上找了很多,但是都没有对计时器控件的深入分析。

有没有比较简单明了的解释来说明上述问题的症结所在? 万分感谢

#3


有限状态自动机举例:
//有字符串
//1_22_333,,4444__55555,_666666
//需要解析为
//1
//22
//333
//_
//4444
//55555
//666666
#include <stdio.h>
char s[]="1_22_333,,4444__55555,_666666";
char c,*p,*p1;
int st;
void main() {
    st=0;
    p=s;
    while (1) {
        c=*p;
        if (0==c) {
            switch (st) {
            case 1:printf("_\n");    break;
            case 2:printf("%s\n",p1);break;
            }
            break;//
        }
        switch (st) {
        case 0:
                 if ('_'==c) {                            st=0;}
            else if (','==c) {                            st=1;}
            else             {p1=p;                       st=2;}
        break;
        case 1:
                 if ('_'==c) {                            st=1;}
            else if (','==c) {printf("_\n");              st=1;}
            else             {p1=p;                       st=2;}
        break;
        case 2:
                 if ('_'==c) {*p=0;printf("%s\n",p1);*p=c;st=0;}
            else if (','==c) {*p=0;printf("%s\n",p1);*p=c;st=1;}
            else             {                            st=2;}
        break;
        }
        p++;
    }
}
//1
//22
//333
//_
//4444
//55555
//666666

#4


不要在程序里面多多个计时器, 也不要在定时器里面自己关掉自己这种动作.

一个计时器就够了, 就像你的手机上可以设置多个闹钟一样, 一个手机一个闹钟那不得烦死? 

效率低, 管理也成问题.

#5


不要在程序里面多多个计时器, 也不要在定时器里面自己关掉自己这种动作.

一个计时器就够了, 就像你的手机上可以设置多个闹钟一样, 一个手机一个闹钟那不得烦死? 

效率低, 管理也成问题.

#6


目前设计的是全自动交易软件, 全天反复进行双向指令交易,最大一天可交易60余笔,一般情况下不会出问题,但有时会出现BUG。首先肯定是计时器的问题。

根据价格的不断变动,实时发送指令,如果不采用大量计时器控制,如何实现自动化??

实际上,虽然采用了数十个计时器,但是实际上只有1-2个计时器在运行。

因为对计时器的原理了解不够,所以才有上述之问。

#7


1)计时器使用时概念上就应该认为是相互独立的,计时器的前后差异会引起BUG,那说明还需要解耦。
2)DoEvents能不用尽量不要用,那是灾难。
3)chrome浏览器开着的时候会对计时器的计时精度产生影响
4)交易这种东西时间精度不该需要太高的,如果时间精度真的要求比较高的话,VB其实是不合适的。

#8


用一个定时器,一次只执行一次交易。
Option Explicit

Private Const TASK_COUNT As Long = 3
Private m_TaskIndex As Long
Private m_aTaskEnabled(0 To TASK_COUNT - 1) As Boolean

Private Sub Command1_Click()
    '设置各交易的活跃状况'
    m_aTaskEnabled(0) = True
    m_aTaskEnabled(1) = False
    m_aTaskEnabled(2) = True
    m_TaskIndex = 0
    
    Timer1.Interval = 100
    Timer1.Enabled = True
End Sub

Private Sub Timer1_Timer()
    Dim i As Long
    Dim lCount As Long
    
    '找到下一个活跃的交易'
    i = m_TaskIndex
    lCount = 0
    Do While lCount < TASK_COUNT
        If m_aTaskEnabled(i) Then Exit Do
    
        i = (i + 1) Mod TASK_COUNT
        lCount = lCount + 1
    Loop
    
    If lCount = TASK_COUNT Then
        Print "没有交易"
    Else
        m_TaskIndex = (i + 1) Mod TASK_COUNT
        Print "交易" & CStr(i + 1)
    End If
End Sub

#9


给段多单的代码,空单也一样:
'************///多单进出场主控制器'buymain计时器逐级控制进场,与buystopmain控制出场

Private Sub BuyMainTimer_Timer()  
 If BuyAimClass <> 11 Then  
  Dim i As Integer
  For i = 1 To 10 
    Me.Controls("BuyTimer" & i).Enabled = False  'BuyTimer
  Next
  
  DoEvents
  Sleep 100
  
  Me.Controls("BuyTimer" & BuyAimClass).Enabled = True
  BuyMainTimer.Enabled = False '
End If
End Sub


Private Sub BuyStopMainTimer_Timer() 
  Dim i As Integer
   For i = 1 To 4
     Me.Controls("BuyStopTimer" & i).Enabled = False
   Next
   
   DoEvents
   Sleep 100
   
   Me.Controls("BuyStopTimer" & BuyHoldClass).Enabled = True
   BuyStopMainTimer.Enabled = False '自关闭
End Sub

Private Sub BuyStopTimer1_Timer()
  If BuyHoldClass = 1 Then
    If Buy1P <= BuyBaseP + N * (BuyAimClass - 1) - N * 2 Then  
     
       MaiChuP Volume * 1, L_Stop
              
       BuyAimClass = BuyAimClass - 1
       BuyHoldClass = 0
       BuyMainTimer.Enabled = True
       
       BuyStopTimer1.Enabled = False '自关闭
    End If
  End If
End Sub




Private Sub BuyTimer1_Timer()
  If Sell1P >= BuyBaseP + N Then       '当价格达到1级目标价格时
   
     DoEvents
     Sleep 100  '保证先平后开   

    MaiRuK Volume, U_Stop

    BuyHoldClass = BuyHoldClass + 1
    BuyAimClass = BuyAimClass + 1
    
BuyMainTimer.Enabled = True 
    BuyStopMainTimer.Enabled = True '持仓后启动止损,无持仓不启动止损
    
    BuyTimer1.Enabled = False  '关闭本计时器

#10


可以随时更改 m_aTaskEnabled(i) 的状态,达到启动/关闭的目的。

#11


每个Timer事件里都有
DoEvents
 Sleep 100
这两行,这是干嘛?

还有,BuyMainTimer.Enabled = False之类的要放在doevents前边,不要放在后边,不然会有事件重入的问题.

#12


另外你可以用Timer数组来代替现在这些,至少名字上可以省心很多

#13


引用 11 楼 bakw 的回复:
每个Timer事件里都有
DoEvents
 Sleep 100
这两行,这是干嘛?

还有,BuyMainTimer.Enabled = False之类的要放在doevents前边,不要放在后边,不然会有事件重入的问题.



1.保证先后顺序。先全部关闭子计时器,后启动对应子计时器,防止走势过快时已启动的子计时器先触发,之后又通过maintimer启动同一个计时器导致重复错误的产生。
2.因为双向监控大量计时器,当多空交换时,若同时触发平仓和开仓,此时将只有一个指令被执行,另一个将失效。在开仓中延时100ms,保证先平后开,避免指令失效问题产生

#14


 1.请教bakw:事件重入是什么情况?

2.后来发现一个问题,因为我在另一个独立运行的计时器(间隔15s)中加入了sleep 1000,假如buytimer1此时刚好触发并进入倒计时,则立即被中断,中断结束后,buytimer1中代码因为尚未执行关闭buytimer1,导致buytimer1又执行一个间隔,相当于同时执行了2次buytimer1,而一旦buytimer1刚刚进入倒计时此时再触发buytimer1将导致完全重复的问题产生。
  不知道我对这个问题的解释对不对?

3.关于timer计时器控制外部计时器timer1的问题:应当是先执行内部指令,之后外部计时器的执行是根据其interval倒计时执行的,因此(举个例子):无论timer中print "hello" 写在timer.enabled=false timer1.enabled=true  前还是后,都先执行print "hello"。关闭自身应也是一样,在执行完timer代码后,隔一个interval才会关闭timer
   

#15


不太理解流程,不过感觉定时器这种用法应该是有问题的
重入的话,比如timer定时是100ms一次的,但timer_timer事件中代码执行时间超过了100ms,这个时候另一个timer_timer事件在doevents调用结束之前又产生了.

#16


引用 15 楼 bakw 的回复:
不太理解流程,不过感觉定时器这种用法应该是有问题的
重入的话,比如timer定时是100ms一次的,但timer_timer事件中代码执行时间超过了100ms,这个时候另一个timer_timer事件在doevents调用结束之前又产生了.


你说的很有道理。
对于重入,查了些资料有些认为会重入,有些认为不会重入。不管重入不重入,刚才测试了以下timer中代码执行的时间基本为0,因此也不会产生重入问题。

在对timer没有深入了解之前就直接进行大量计时器交替控制操作,因此产生了这样那样奇怪的不同步问题。比如原来觉得代码是顺序执行的,没有考虑到间隔问题,以为timer1.enabled=true (false)后timer2.enabled=true (false)就先启动timer1后启动2,后来才发现不是这样的。

我是VB新手,平常上班较忙,因此2个月的时间编了一个外挂专门用于15秒-1分钟级期货自动交易策略测试,点击启动后一整天就不用再管了,程序自动发送交易指令,目前基本运行稳定,但是不时有各种bug出现。今天测试了一整天,才基本找到一个问题的原因,已经改好了,但效果仍需测试,新的问题仍旧有可能发生。

大量timer确实不好控制,有一点没有照顾到就容易不按设计出牌,需要深入了解其脾性。现在主要采用的是交替控制,触发条件即关闭并通过主控重新选择新的计时器。


对于timer控件的原理还有不少疑惑,不知哪里有比较深入详细的学习资料,msdn已经看过了。


#17


重入会导致程序无法正常退出,需要用End强行退出,我写过几个通讯程序,因为在通讯等待的时候用了doevents就造成这样的后果:在doevents的时候执行了unload退出,等从doevents返回的时候,对象已经被卸载了,结果程序又不得不重建一个实例,好让doevents有地方可以返回,但这个时候,所有的状态变量已经被清空了,所以程序又无法知道,在doevents里的时候其实已经是执行了退出的。于是变成了一个退不掉的后台程序。
详细资料没有看到过,VB是单线程的程序,尽可能从这个角度去理解Timer会好一些.

#18


你的程序用法,类似于把定时器当成线程,可惜VB是单线程的,一个确定时刻程序只处于一个确定的位置。

#19


该回复于2015-01-02 11:09:52被管理员删除

#20


感觉好复杂的样子~

#21


计算可以开线程,VB可以用API开线程
1)定时器不要做太多的工作,否则会有积压
2)定时器不要Sleep,Sleep 会造成定时器积压 
积压的定时器,会造成界面和其他操作延迟

定时的时间间隔不要太小,虽然定时器,代码简短时候,可以保证
 时间间隔小的操作,平均时间间隔的得到保证
但是会瞬间连续启动n 次定时器,不是你想要的

定时器的界面操作也不宜太多,更多的界面操作,还是交给事件处理
PS:
定时器不宜太多

#22


定时器的原理,
是利用硬件定时器中断程序的时机,
安排一段独立的代码,
该代码利用线程的时间片,
和线程分时并行运行,
可以看作作线程的一个分支程序,
----------线程正常运行时候,只有一条运行路线,开定时器有两天运行路线---------


#23


学习了,加油楼煮

#24


计时器运行的原理与大量计时器不同步问题

#25


不错,收藏下 计时器运行的原理与大量计时器不同步问题

#26


感觉好复杂的样子~

#27


好的,不错,给力

#28


好多大神……………………………………………………………………

#29


计时器运行的原理与大量计时器不同步问题

#30


learning

#31


沙发一个 计时器运行的原理与大量计时器不同步问题

#32


vb不能多线程,用vb.net吧。我的自动化交易用两个线程解决,一个接受行情,一个计算并交易。

#33


mark 计时器运行的原理与大量计时器不同步问题

#34


引用 22 楼 lm_whales 的回复:
定时器的原理,
是利用硬件定时器中断程序的时机,
安排一段独立的代码,
该代码利用线程的时间片,
和线程分时并行运行,
可以看作作线程的一个分支程序,
----------线程正常运行时候,只有一条运行路线,开定时器有两天运行路线---------

计时器运行的原理与大量计时器不同步问题

#35


该回复于2015-01-03 17:25:00被管理员删除

#36


该回复于2015-01-04 10:08:53被管理员删除

#37


讨论得太高深了,根本看不懂,不过把楼主的程序复制运行一下,结果与讨论所确定的命题有所不同,但确满足楼主的需求,好奇了...

#38


想上传一个20K的截图,点上传,在那儿转了十几分钟圈子,CSDN 消亡恐怕快了.

#39


计时器运行的原理与大量计时器不同步问题

#40


厉害,学习到很多

#41


想上传一个20K的截图,点上传,在那儿转了十几分钟圈子,CSDN 消亡恐怕快了

#42


计时器同步有时是特别重要的问题

#43


该回复于2015-01-05 10:02:10被管理员删除

#44


该回复于2015-01-05 10:03:33被管理员删除

#45


多定时器完全是设计错误,按我#8的例子用单个定时器就能实现的。
楼主你想太多了!

#46


感觉好复杂,学习了~

#47


理论上来说三个计时器干的活,应该是相应没有影响,没有任何关系的。
如果有关系或是有先后顺序,应该是一个计时器来控置。
或者是一个计时器完了,再调下一个计时器。

#48


提醒:处理不过来时需要使用FIFO队列保存请求和结果,并监视FIFO队列防止溢出。

#49


引用 21 楼 lm_whales 的回复:
计算可以开线程,VB可以用API开线程
1)定时器不要做太多的工作,否则会有积压
2)定时器不要Sleep,Sleep 会造成定时器积压 
积压的定时器,会造成界面和其他操作延迟

定时的时间间隔不要太小,虽然定时器,代码简短时候,可以保证
 时间间隔小的操作,平均时间间隔的得到保证
但是会瞬间连续启动n 次定时器,不是你想要的

定时器的界面操作也不宜太多,更多的界面操作,还是交给事件处理
PS:
定时器不宜太多



实际上最多的时候一次使用了120个计时器,但是由于交替控制,因此一次只有不超过3个计时器在运行,其他计时器全部处于关闭状态。
您说的sleep问题确实存在,后来专门进行了测试:两个计时器,一个间隔(1000ms)代码为sleep 1000,另一个间隔(2000ms)代码为print "hello"并获取执行代码的毫秒级时间,结果是print"hello"发生在3000ms之后,有时发生在1000ms后


我现在又遇到一个问题:buystopmaintimer为主控,buystoptimer1为子控  interval全为100ms,代码如下。正常情况下应该是buystoptimer1触发后自行关闭不会被触发,但是在实际运行过程中,偶尔会出现重复发送代码指令的问题。(备注:产生问题的可能原因:第三方计时器中有一次doevents sleep 50的代码,若同时触发可能产生这个问题,但是按照我在上述的测试,sleep后被中断倒计时的buystoptimer1r应当会继续执行代码而不是又执行一个间隔)

Private Sub BuyStopMainTimer_Timer() 
   Dim i As Integer
   For i = 1 To 4
     Me.Controls("BuyStopTimer" & i).Enabled = False
   Next
   
   DoEvents
   Sleep 50
   
   Me.Controls("BuyStopTimer" & BuyHoldClass).Enabled = True
   BuyStopMainTimer.Enabled = False '自关闭
End Sub

Private Sub BuyStopTimer1_Timer()
  If BuyHoldClass = 1 Then
    If Buy1P <= BuyBaseP + N * (BuyAimClass - 1) - N * 2 Then 
       
       MaiChuP Volume * 1, L_Stop
                                 
       BuyAimClass = BuyAimClass - 1        
       BuyHoldClass = 0         
           
       BuyTimer2.Enabled = False         
       BuyStopTimer1.Enabled = False '自关闭
    End If
  End If

#50


引用 32 楼 u011326712 的回复:
vb不能多线程,用vb.net吧。我的自动化交易用两个线程解决,一个接受行情,一个计算并交易。


计时器运行的原理与大量计时器不同步问题

俺现在用的程序框架是用三个计时器同时运行,一个计时器获取行情,一个计时器连接数据库计算均线,一个计时器作为进出场主控制器。 我是新手,大学学过一点vb,就用6.0编了一个,线程问题还是最近才了解。很有用的参考,谢谢!