点击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个计时器在运行。
因为对计时器的原理了解不够,所以才有上述之问。
根据价格的不断变动,实时发送指令,如果不采用大量计时器控制,如何实现自动化??
实际上,虽然采用了数十个计时器,但是实际上只有1-2个计时器在运行。
因为对计时器的原理了解不够,所以才有上述之问。
#7
1)计时器使用时概念上就应该认为是相互独立的,计时器的前后差异会引起BUG,那说明还需要解耦。
2)DoEvents能不用尽量不要用,那是灾难。
3)chrome浏览器开着的时候会对计时器的计时精度产生影响
4)交易这种东西时间精度不该需要太高的,如果时间精度真的要求比较高的话,VB其实是不合适的。
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 '关闭本计时器
'************///多单进出场主控制器'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前边,不要放在后边,不然会有事件重入的问题.
DoEvents
Sleep 100
这两行,这是干嘛?
还有,BuyMainTimer.Enabled = False之类的要放在doevents前边,不要放在后边,不然会有事件重入的问题.
#12
另外你可以用Timer数组来代替现在这些,至少名字上可以省心很多
#13
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
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调用结束之前又产生了.
重入的话,比如timer定时是100ms一次的,但timer_timer事件中代码执行时间超过了100ms,这个时候另一个timer_timer事件在doevents调用结束之前又产生了.
#16
你说的很有道理。
对于重入,查了些资料有些认为会重入,有些认为不会重入。不管重入不重入,刚才测试了以下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会好一些.
详细资料没有看到过,VB是单线程的程序,尽可能从这个角度去理解Timer会好一些.
#18
你的程序用法,类似于把定时器当成线程,可惜VB是单线程的,一个确定时刻程序只处于一个确定的位置。
#19
#20
感觉好复杂的样子~
#21
计算可以开线程,VB可以用API开线程
1)定时器不要做太多的工作,否则会有积压
2)定时器不要Sleep,Sleep 会造成定时器积压
积压的定时器,会造成界面和其他操作延迟
定时的时间间隔不要太小,虽然定时器,代码简短时候,可以保证
时间间隔小的操作,平均时间间隔的得到保证
但是会瞬间连续启动n 次定时器,不是你想要的
定时器的界面操作也不宜太多,更多的界面操作,还是交给事件处理
PS:
定时器不宜太多
1)定时器不要做太多的工作,否则会有积压
2)定时器不要Sleep,Sleep 会造成定时器积压
积压的定时器,会造成界面和其他操作延迟
定时的时间间隔不要太小,虽然定时器,代码简短时候,可以保证
时间间隔小的操作,平均时间间隔的得到保证
但是会瞬间连续启动n 次定时器,不是你想要的
定时器的界面操作也不宜太多,更多的界面操作,还是交给事件处理
PS:
定时器不宜太多
#22
定时器的原理,
是利用硬件定时器中断程序的时机,
安排一段独立的代码,
该代码利用线程的时间片,
和线程分时并行运行,
可以看作作线程的一个分支程序,
----------线程正常运行时候,只有一条运行路线,开定时器有两天运行路线---------
是利用硬件定时器中断程序的时机,
安排一段独立的代码,
该代码利用线程的时间片,
和线程分时并行运行,
可以看作作线程的一个分支程序,
----------线程正常运行时候,只有一条运行路线,开定时器有两天运行路线---------
#23
学习了,加油楼煮
#24
#25
不错,收藏下
#26
感觉好复杂的样子~
#27
好的,不错,给力
#28
好多大神……………………………………………………………………
#29
#30
learning
#31
沙发一个
#32
vb不能多线程,用vb.net吧。我的自动化交易用两个线程解决,一个接受行情,一个计算并交易。
#33
mark
#34
#35
#36
#37
讨论得太高深了,根本看不懂,不过把楼主的程序复制运行一下,结果与讨论所确定的命题有所不同,但确满足楼主的需求,好奇了...
#38
想上传一个20K的截图,点上传,在那儿转了十几分钟圈子,CSDN 消亡恐怕快了.
#39
#40
厉害,学习到很多
#41
想上传一个20K的截图,点上传,在那儿转了十几分钟圈子,CSDN 消亡恐怕快了
#42
计时器同步有时是特别重要的问题
#43
#44
#45
多定时器完全是设计错误,按我#8的例子用单个定时器就能实现的。
楼主你想太多了!
楼主你想太多了!
#46
感觉好复杂,学习了~
#47
理论上来说三个计时器干的活,应该是相应没有影响,没有任何关系的。
如果有关系或是有先后顺序,应该是一个计时器来控置。
或者是一个计时器完了,再调下一个计时器。
如果有关系或是有先后顺序,应该是一个计时器来控置。
或者是一个计时器完了,再调下一个计时器。
#48
提醒:处理不过来时需要使用FIFO队列保存请求和结果,并监视FIFO队列防止溢出。
#49
实际上最多的时候一次使用了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
俺现在用的程序框架是用三个计时器同时运行,一个计时器获取行情,一个计时器连接数据库计算均线,一个计时器作为进出场主控制器。 我是新手,大学学过一点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个计时器在运行。
因为对计时器的原理了解不够,所以才有上述之问。
根据价格的不断变动,实时发送指令,如果不采用大量计时器控制,如何实现自动化??
实际上,虽然采用了数十个计时器,但是实际上只有1-2个计时器在运行。
因为对计时器的原理了解不够,所以才有上述之问。
#7
1)计时器使用时概念上就应该认为是相互独立的,计时器的前后差异会引起BUG,那说明还需要解耦。
2)DoEvents能不用尽量不要用,那是灾难。
3)chrome浏览器开着的时候会对计时器的计时精度产生影响
4)交易这种东西时间精度不该需要太高的,如果时间精度真的要求比较高的话,VB其实是不合适的。
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 '关闭本计时器
'************///多单进出场主控制器'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前边,不要放在后边,不然会有事件重入的问题.
DoEvents
Sleep 100
这两行,这是干嘛?
还有,BuyMainTimer.Enabled = False之类的要放在doevents前边,不要放在后边,不然会有事件重入的问题.
#12
另外你可以用Timer数组来代替现在这些,至少名字上可以省心很多
#13
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
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调用结束之前又产生了.
重入的话,比如timer定时是100ms一次的,但timer_timer事件中代码执行时间超过了100ms,这个时候另一个timer_timer事件在doevents调用结束之前又产生了.
#16
你说的很有道理。
对于重入,查了些资料有些认为会重入,有些认为不会重入。不管重入不重入,刚才测试了以下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会好一些.
详细资料没有看到过,VB是单线程的程序,尽可能从这个角度去理解Timer会好一些.
#18
你的程序用法,类似于把定时器当成线程,可惜VB是单线程的,一个确定时刻程序只处于一个确定的位置。
#19
#20
感觉好复杂的样子~
#21
计算可以开线程,VB可以用API开线程
1)定时器不要做太多的工作,否则会有积压
2)定时器不要Sleep,Sleep 会造成定时器积压
积压的定时器,会造成界面和其他操作延迟
定时的时间间隔不要太小,虽然定时器,代码简短时候,可以保证
时间间隔小的操作,平均时间间隔的得到保证
但是会瞬间连续启动n 次定时器,不是你想要的
定时器的界面操作也不宜太多,更多的界面操作,还是交给事件处理
PS:
定时器不宜太多
1)定时器不要做太多的工作,否则会有积压
2)定时器不要Sleep,Sleep 会造成定时器积压
积压的定时器,会造成界面和其他操作延迟
定时的时间间隔不要太小,虽然定时器,代码简短时候,可以保证
时间间隔小的操作,平均时间间隔的得到保证
但是会瞬间连续启动n 次定时器,不是你想要的
定时器的界面操作也不宜太多,更多的界面操作,还是交给事件处理
PS:
定时器不宜太多
#22
定时器的原理,
是利用硬件定时器中断程序的时机,
安排一段独立的代码,
该代码利用线程的时间片,
和线程分时并行运行,
可以看作作线程的一个分支程序,
----------线程正常运行时候,只有一条运行路线,开定时器有两天运行路线---------
是利用硬件定时器中断程序的时机,
安排一段独立的代码,
该代码利用线程的时间片,
和线程分时并行运行,
可以看作作线程的一个分支程序,
----------线程正常运行时候,只有一条运行路线,开定时器有两天运行路线---------
#23
学习了,加油楼煮
#24
#25
不错,收藏下
#26
感觉好复杂的样子~
#27
好的,不错,给力
#28
好多大神……………………………………………………………………
#29
#30
learning
#31
沙发一个
#32
vb不能多线程,用vb.net吧。我的自动化交易用两个线程解决,一个接受行情,一个计算并交易。
#33
mark
#34
#35
#36
#37
讨论得太高深了,根本看不懂,不过把楼主的程序复制运行一下,结果与讨论所确定的命题有所不同,但确满足楼主的需求,好奇了...
#38
想上传一个20K的截图,点上传,在那儿转了十几分钟圈子,CSDN 消亡恐怕快了.
#39
#40
厉害,学习到很多
#41
想上传一个20K的截图,点上传,在那儿转了十几分钟圈子,CSDN 消亡恐怕快了
#42
计时器同步有时是特别重要的问题
#43
#44
#45
多定时器完全是设计错误,按我#8的例子用单个定时器就能实现的。
楼主你想太多了!
楼主你想太多了!
#46
感觉好复杂,学习了~
#47
理论上来说三个计时器干的活,应该是相应没有影响,没有任何关系的。
如果有关系或是有先后顺序,应该是一个计时器来控置。
或者是一个计时器完了,再调下一个计时器。
如果有关系或是有先后顺序,应该是一个计时器来控置。
或者是一个计时器完了,再调下一个计时器。
#48
提醒:处理不过来时需要使用FIFO队列保存请求和结果,并监视FIFO队列防止溢出。
#49
实际上最多的时候一次使用了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
俺现在用的程序框架是用三个计时器同时运行,一个计时器获取行情,一个计时器连接数据库计算均线,一个计时器作为进出场主控制器。 我是新手,大学学过一点vb,就用6.0编了一个,线程问题还是最近才了解。很有用的参考,谢谢!