打个比方:2个按钮运行
第一个按钮点了运行到一半,点了第二个按钮,程序会运行第二个按钮的事件
直到第二个按钮的事件运行结束,再把第一个按钮的事件运行完,想解决上边的问题有没有什么好的办法:
触发了第二个按钮的事件后能不能判断下有没别的没运行完,有的话让它先运行完
第一个按钮点了运行到一半,点了第二个按钮,程序会运行第二个按钮的事件
直到第二个按钮的事件运行结束,再把第一个按钮的事件运行完,想解决上边的问题有没有什么好的办法:
触发了第二个按钮的事件后能不能判断下有没别的没运行完,有的话让它先运行完
不会吧?除非你在第一个事件代码中插入 DoEvents 等着第二个事件。即便如此,也可以采用“令牌”方式。例如,用一个全局变量 Public Running As Boolean。每个事件代码中都加上:Private Sub xxxx(...)If Running Then Exit SubRunning = True...... '原来的事件代码Running = FalseEnd Sub此外,还可以禁止按钮:Private Sub Command1_Click()
Command1.Enabled = False
Command2.Enabled = False...... '原来的事件代码Command1.Enabled = True
Command2.Enabled = True
End Sub
Call Roll(Index)
End Sub
Private Sub Roll(ByVal Index As Integer)
Dim i As Long
For i = 1 To 100000
Label1(Index).Caption = i
DoEvents
Next
End Sub这是测试,两个数组按钮btnRoll,2个标签Label1
1 To 100000
太长了
改成 1 To 10000点 第一个(第一次),马上又点第二个 ,接着又点第一个(第二次)Label1 转了一部分 停下了 ,Label2 开始转 ,又停下了,然后 Label1 从1 开始直到结束
Label2 开始接着转直到结束,Label1 从第一次停下的地方开始转直到结束。
这是正常效果,这两个按钮,不管你连续点了多少次,Roll就执行多少次,
最后点的先执行完,最开始点的压在栈中 ,最后执行完。楼主想要实现什么样的效果?
不过会有个后遗症,就是主线程卡死~~~
Private Sub btnRoll_Click(Index As Integer)
btnRoll(Index).Enabled = False
inx = Index
Timer1.Enabled = True
End Sub
Private Sub Roll(ByVal Index As Integer)
runing = True
Dim i As Long
For i = 1 To 10000
Label1(Index).Caption = i
DoEvents
Next
runing = False
btnRoll(Index).Enabled = True
End SubPrivate Sub Form_Load()
Timer1.Enabled = False
Timer1.Interval = 10
End SubPrivate Sub Timer1_Timer()
If runing Then Exit Sub
Timer1.Enabled = False
Call Roll(inx)
End Sub
即使不加doevents也会被中断
分不够可以加,300分也可以用enable或者直接退出当前工程的,这不是我要的效果,解决不了现在的问题
我在vb里老是用不起来,不知道哪位大虾能用到上边5楼的例子中去就好了
不过如果你的Command1_Click中含有DoEvents语句,那么系统就会使Command1_Click让出CPU时间,来响应其它的事件,所以:Command2_Click事件就有可能被执行了。要实现楼主的想法,最好是用多线程,不过,VB6.0不能良好的支持多线程,并不可行。所以在Command1_Click的合适位置加入DoEvents是一个可行的办法。
能不能读到这个点,让他运行,或者把下一个函数的优先级调到最低(如果当前有别的过程正在执行,那么等待那个函数执行完,并且把运行点还给它)
Private Sub btnRoll_Click(Index As Integer)
if runing then
'等待 并 让前面的Roll继续运行
do while runing
DoEvents
'看起来很美 但一定不管用 ,如果不用多线程,还是只有用 timer
'不用timer,也许这个对你有用
'http://www.vbgood.com/viewthread.php?tid=93124&extra=&page=1
loop
end if
Roll Index
End Sub
Private Sub Roll(ByVal Index As Integer)
runing = True
Dim i As Long
For i = 1 To 10000
Label1(Index).Caption = i
DoEvents
Next
runing = False
End Sub
1运行后,运行2,1被中断,
你上边的效果是2不停的循环判断那个全局变量值,
但是1被中断了,并没有任何运行,1也不会运行到结束,去改变全局变量runing = False最后就是2的循环永远不退出,而1还在等待2运行完再继续运行
于是程序会变成这样:按第一下,程序开始跑,按第二次的时候主线程卡死了,整个程序处于无响应状态。然后等第一个跑完了,第二个才开始跑,程序界面恢复响应。这时候按第三次,主线程又卡死了。
这是的很大的工程,不敢,也不想去用那个,
其实可以把这个函数写到别的exe里边用等待进程结束或许可以达到效果,
但是最好也不想这么做软件结构也不太可能改
peekmessage 0,0,0,0,pm_remove
TranslateMessage
DispatchMessage
sleep 0doevents之所以能释放cpu资源,在于 sleep 0,之所以能改变流程在于 DispatchMessage,DispatchMessage接受来自getmessage取自消息队列的消息,然后发往相应的窗口执行,于是乎我一直觉得这个应该是靠着栈堆实现的所谓的异步应该是getmessage作用,刚才灵光闪现,终于想通了
DispatchMessage
这些vb怎么用
不可能递归的消息先执行外层消息;
晕死,这样完全混乱
Option ExplicitPrivate mblnRunning As Boolean
Private mlngCount As LongPrivate Sub DoTask()
Dim i As Long
For i = 0 To 1000000
DoEvents
Next
Debug.Print "Done"
End SubPrivate Sub Command1_Click()
If mblnRunning Then
mlngCount = mlngCount + 1
Exit Sub
End If
Do
Call DoTask
mlngCount = mlngCount - 1
Loop While mlngCount > 0
End Sub
Private mlngCount As LongPrivate Sub DoTask()
Dim i As Long
For i = 0 To 1000000
DoEvents
Next
Static c As Long
c = c + 1
Debug.Print c & " Done"
End SubPrivate Sub Command1_Click()
Static c As Long
c = c + 1
Debug.Print c & " Clicked!"
If mblnRunning Then
mlngCount = mlngCount + 1
Exit Sub
End If
mlngCount = mlngCount + 1
mblnRunning = True
Do
Call DoTask
mlngCount = mlngCount - 1
Loop While mlngCount > 0
mblnRunning = False
End Sub
Option ExplicitPrivate mlngtaskid As LongPrivate Sub Command1_Click()
mlngtaskid = mlngtaskid + 1
Dim lngTaskID As Long
lngTaskID = mlngtaskid
Debug.Print lngTaskID & " Clicked!"
Dim i As Long
For i = 0 To 1000000
Do
DoEvents
Loop While lngTaskID <> mlngtaskid
Next mlngtaskid = mlngtaskid - 1
Debug.Print lngTaskID & " Done!"
End Sub
2 Clicked!
2 Done!
1 Done!
2 Clicked!
1 Done!
2 Done!
debug显示内容不对,应该改一下
Option ExplicitPrivate mblnRunning As Boolean
Private mlngCount As LongPrivate Sub DoTask(ByVal d As Long)
Dim i As Long
For i = 0 To 1000000
DoEvents
Next
Debug.Print d & " Done"
End SubPrivate Sub Command1_Click()
Static c As Long
c = c + 1
Debug.Print c & " Clicked!"
If mblnRunning Then
mlngCount = mlngCount + 1
Exit Sub
End If
mlngCount = mlngCount + 1
mblnRunning = True
Do
Call DoTask(c)
mlngCount = mlngCount - 1
Loop While mlngCount > 0
mblnRunning = False
End Sub结果
1 Clicked!
2 Clicked!
3 Clicked!
1 Done
3 Done
3 Done
等我改一下你就看出来了...
Option ExplicitPrivate mblnRunning As Boolean
Private mCol As New CollectionPrivate Function GenID() As Long
Static id As Long
id = id + 1
GenID = id
End Function
Private Sub Command1_Click()
Static c As Long
c = c + 1
Debug.Print c & " Clicked!"
Dim ti As TaskInfo
Set ti = New TaskInfo
Call ti.SetUp(GenID())
Call mCol.Add(ti)
If mblnRunning Then
Exit Sub
End If
mblnRunning = True
Do
Call mCol.Item(1).DoTask
Call mCol.Remove(1)
Loop While mCol.Count > 0
mblnRunning = False
End SubTaskInfo.cls代码
Option ExplicitPrivate mlngID As LongPublic Sub SetUp(ByRef id As Long)
mlngID = id
End Sub
Public Sub DoTask()
Dim i As Long
For i = 0 To 1000000
DoEvents
Next
Debug.Print mlngID & " Done!"
End Sub
Private mCol As New CollectionPrivate Sub Command1_Click()
Static c As Long
c = c + 1
Debug.Print c & " Clicked!"
Dim ti As TaskInfo
Set ti = New TaskInfo
Call ti.SetUp(c)
Call mCol.Add(ti)
If mblnRunning Then
Exit Sub
End If
mblnRunning = True
Do
Call mCol.Item(1).DoTask
Call mCol.Remove(1)
Loop While mCol.Count > 0
mblnRunning = False
End Sub这样也行:)
打个比方
3个不同的按钮(有的可能是别的各不相同的事件),中间有段代码需要调用GenID
GenID是有参数有返回的,并且调用的GenID之后并且用GenID的返回值去进行接下去的计算
Option ExplicitPrivate mblnRunning As Boolean
Private mCol As New CollectionPrivate Sub Command1_Click()
Debug.Print "1 clicked"
Call test(1)
End SubPrivate Sub Command2_Click()
Debug.Print "2 clicked"
Call test(2)
End SubPrivate Sub Command3_Click()
Debug.Print "3 clicked"
Call test(3)
End SubPrivate Sub test(ByVal nIn As Long)
Dim ti As TaskInfo
Set ti = New TaskInfo
Call ti.SetUp(nIn)
Call mCol.Add(ti)
If mblnRunning Then
Exit Sub
End If
mblnRunning = True
Do
Call mCol.Item(1).DoTask
Call mCol.Remove(1)
Loop While mCol.Count > 0
mblnRunning = False
End Sub
Option ExplicitPrivate mblnRunning As Boolean
Private mCol As New CollectionPrivate Sub Command1_Click()
Debug.Print "1 clicked"
debug.print test(1)
End SubPrivate Sub Command2_Click()
Debug.Print "2 clicked"
debug.print test(2)
End SubPrivate Sub Command3_Click()
Debug.Print "3 clicked"
debug.print test(3)
End SubPrivate Sub test(ByVal nIn As Long) as long
Dim ti As TaskInfo
Set ti = New TaskInfo
Call ti.SetUp(nIn)
Call mCol.Add(ti)
If mblnRunning Then
Exit Sub
End If
mblnRunning = True
Do
Call mCol.Item(1).DoTask
Call mCol.Remove(1)
Loop While mCol.Count > 0
mblnRunning = False
End Sub