找回密码
 加入
搜索
查看: 2859|回复: 10

[网络通信] 请教一个关于循环执行任务的问题

  [复制链接]
发表于 2019-12-29 19:11:21 | 显示全部楼层 |阅读模式
本帖最后由 水木子 于 2019-12-29 19:21 编辑

最近在帮朋友写一个小程序,涉及到需要循环挨个执行任务,一直没有什么好的方法,特来请教下大家,还望大家不吝赐教。

我先说明下需求吧!
1、每个循环的循环次数是不定的,不一定都是10次。
2、必须等前面的循环执行完毕,再接着执行后面的循环。比如勾选了 “循环2”和“循环4”,那么就先执行完“循环2”,之后再开始“循环4”
3、可随时相应按钮控制,比如循环开始以后,可以点击“结束”按钮,立即结束循环。

不知道我表达清楚没有,目前我的解决方法如下,但是我始终觉得不够好。还请大家帮忙想想有没有其他更好的方法。
看似一个挺简单的问题,但我思索了许久,一直没有想出比较好的解决方法。
Global $bBoolean = True, $iZ
Global $Checkbox[4]
Global $hGUI = GUICreate('', 300, 400)
$Checkbox[0] = GUICtrlCreateCheckbox('循环1', 60, 50, 97, 17)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')
$Checkbox[1] = GUICtrlCreateCheckbox('循环2', 180, 50, 97, 17)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')
$Checkbox[2] = GUICtrlCreateCheckbox('循环3', 60, 100, 97, 17)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')
$Checkbox[3] = GUICtrlCreateCheckbox('循环4', 180, 100, 97, 17)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')

$Label1 = GUICtrlCreateLabel('', 50, 200, 200, 20, 0x01 + 0x0200)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')
$Label2 = GUICtrlCreateLabel('准备就绪', 50, 250, 200, 20, 0x01 + 0x0200)
GUICtrlSetFont(-1, 14, 400, 0, '微软雅黑')

$Button1 = GUICtrlCreateButton('开始', 50, 300, 80, 30)
$Button2 = GUICtrlCreateButton('结束', 170, 300, 80, 30)
GUISetState()

While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
                Case -3
                        Exit
                Case $Button1
                        $bBoolean = True
                        If GUICtrlRead($Checkbox[0]) = 1 and $bBoolean = True Then
                                $bBoolean = False
                                $iZ = 0
                                GUICtrlSetData($Label1, '正在执行 循环1')
                                AdlibRegister('MyFunc', 500)

                                Wait()
                        EndIf

                        If GUICtrlRead($Checkbox[1]) = 1 and $bBoolean = True  Then
                                $bBoolean = False
                                $iZ = 0
                                GUICtrlSetData($Label1, '正在执行 循环2')
                                AdlibRegister('MyFunc', 500)

                                Wait()
                        EndIf

                        If GUICtrlRead($Checkbox[2]) = 1 and $bBoolean = True  Then
                                $bBoolean = False
                                $iZ = 0
                                GUICtrlSetData($Label1, '正在执行 循环3')
                                AdlibRegister('MyFunc', 500)

                                Wait()
                        EndIf

                        If GUICtrlRead($Checkbox[3]) = 1 and $bBoolean = True  Then
                                $bBoolean = False
                                $iZ = 0
                                GUICtrlSetData($Label1, '正在执行 循环4')
                                AdlibRegister('MyFunc', 500)

                                Wait()
                        EndIf

                Case $Button2
                        AdlibUnRegister()
                        $bBoolean = False
                        GUICtrlSetData($Label1, '手动结束循环')

        EndSwitch
WEnd

Func Wait()
        While 1
                If $bBoolean = True Then ExitLoop

                $nMsg2 = GUIGetMsg()
                Switch $nMsg2
                        Case -3
                                Exit

                        Case $Button2
                                AdlibUnRegister()
                                $bBoolean = False
                                GUICtrlSetData($Label1, '手动结束循环')
                                ExitLoop
                EndSwitch
        WEnd
EndFunc   ;==>Wait

Func MyFunc()
        $iZ += 1
        GUICtrlSetData($Label2, $iZ)

        If $iZ = 10 Then
                AdlibUnRegister()
                $bBoolean = True
                GUICtrlSetData($Label1, '循环完成')
        EndIf
EndFunc   ;==>MyFunc


发表于 2019-12-29 19:18:13 | 显示全部楼层
挺好的 好像木有问题啊~~
 楼主| 发表于 2019-12-29 19:20:31 | 显示全部楼层
afan 发表于 2019-12-29 19:18
挺好的 好像木有问题啊~~

谢谢前辈的支持,请不要受我代码的影响,如果让你来写,这样的问题,你会用什么方法呢?
发表于 2019-12-29 19:48:34 | 显示全部楼层
本帖最后由 afan 于 2019-12-29 19:51 编辑

不知道木子的用途,我只能按自己的方式搞一下
Opt('GUIOnEventMode', 1)

Global $hGUI, $Checkbox[4], $Label1, $Label2, $Button2
_Test()

Func _Test()
        $hGUI = GUICreate('', 300, 400)
        GUISetFont(12, 400, 0, '微软雅黑')
        GUISetOnEvent(-3, '_Close')
        $Checkbox[0] = GUICtrlCreateCheckbox('循环1', 60, 50, 97, 17)
        $Checkbox[1] = GUICtrlCreateCheckbox('循环2', 180, 50, 97, 17)
        $Checkbox[2] = GUICtrlCreateCheckbox('循环3', 60, 100, 97, 17)
        $Checkbox[3] = GUICtrlCreateCheckbox('循环4', 180, 100, 97, 17)
        $Label1 = GUICtrlCreateLabel('', 50, 200, 200, 20, 0x01 + 0x0200)
        $Label2 = GUICtrlCreateLabel('准备就绪', 50, 250, 200, 20, 0x01 + 0x0200)
        GUICtrlCreateButton('开始', 50, 300, 80, 30)
        GUICtrlSetOnEvent(-1, '_Start')
        $Button2 = GUICtrlCreateButton('结束', 170, 300, 80, 30)
        GUISetState()
        While 1
                Sleep(1000)
        WEnd
EndFunc   ;==>_Test

Func _Start()
        Opt('GUIOnEventMode', 0)
        For $ii = 0 To 3
                If GUICtrlRead($Checkbox[$ii]) = 1 Then
                        GUICtrlSetData($Label1, '正在执行 循环' & $ii + 1)
                        For $jj = 1 To 10
                                $ts = TimerInit()
                                Do
                                        Switch GUIGetMsg()
                                                Case -3
                                                        _Close()
                                                Case $Button2
                                                        GUICtrlSetData($Label1, '手动结束循环')
                                                        ExitLoop 3
                                        EndSwitch
                                Until TimerDiff($ts) > 500
                                GUICtrlSetData($Label2, $jj)
                        Next
                        GUICtrlSetData($Label1, '循环完成')
                EndIf
        Next
        Opt('GUIOnEventMode', 1)
EndFunc   ;==>_Start

Func _Close()
        Exit
EndFunc   ;==>_Close

评分

参与人数 1金钱 +100 收起 理由
水木子 + 100 谢谢!学习了。

查看全部评分

 楼主| 发表于 2019-12-29 19:57:23 | 显示全部楼层
本帖最后由 水木子 于 2019-12-29 19:58 编辑
afan 发表于 2019-12-29 19:48
不知道木子的用途,我只能按自己的方式搞一下
Opt('GUIOnEventMode', 1)

是这样的,这个小程序的主要作用是,定时监测某窗口上是否出现某按钮,如果出现了则按下,$iZ += 1
如此往复 当 $iZ =  n  则结束循环,继续执行下一个循环。中途可以手动停止监测。就是这么回事。
另外前辈给出的代码,我这边执行出错。Until TimerDiff($ts) $ts未申明。
发表于 2019-12-29 20:03:30 | 显示全部楼层
本帖最后由 zghwelcome 于 2019-12-29 20:05 编辑


#include <WindowsConstants.au3>
Global $bBoolean = True
Global $Checkbox[4]
Global $hGUI = GUICreate('', 300, 400)
$Checkbox[0] = GUICtrlCreateCheckbox('循环1', 60, 50, 97, 17)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')
$Checkbox[1] = GUICtrlCreateCheckbox('循环2', 180, 50, 97, 17)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')
$Checkbox[2] = GUICtrlCreateCheckbox('循环3', 60, 100, 97, 17)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')
$Checkbox[3] = GUICtrlCreateCheckbox('循环4', 180, 100, 97, 17)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')

$Label1 = GUICtrlCreateLabel('', 50, 200, 200, 20, 0x01 + 0x0200)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')
$Label2 = GUICtrlCreateLabel('准备就绪', 50, 250, 200, 20, 0x01 + 0x0200)
GUICtrlSetFont(-1, 14, 400, 0, '微软雅黑')

$Button1 = GUICtrlCreateButton('开始', 50, 300, 80, 30)
$Button2 = GUICtrlCreateButton('结束', 170, 300, 80, 30)
GUISetState()
GUIRegisterMsg($WM_SYSCOMMAND, "On_WM_SYSCOMMAND")
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
                Case -3
                        Exit
                Case $Button1
                        $bBoolean = True
                        For $i = 0 To UBound($Checkbox) - 1
                                If Not $bBoolean Then ExitLoop
                                If GUICtrlRead($Checkbox[$i]) = 1 Then
                                        Local $vLoopNum = Random(5,10,1)
                                        GUICtrlSetData($Label1, '正在执行 循环' & $i + 1)
                                        _Loop($i + 1 ,$vLoopNum)
                                EndIf
                        Next
                        
        EndSwitch
WEnd


Func _Loop($vLoopIndex , $vLoopNum)
        For $j = 1 To $vLoopNum
                GUICtrlSetData($Label2, '循环' & $vLoopIndex & '    ' & $j & '/' & $vLoopNum)
                For $t = 1 To 2
                        Sleep(250)
                        If Not $bBoolean Then Return GUICtrlSetData($Label1, '手动结束循环')
                Next
        Next
EndFunc   ;==>_Loop


Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam)
        $iCode = BitShift($iwParam, 16)
        Switch $ilParam
                Case GUICtrlGetHandle($Button2)
                        $bBoolean = False                        
        EndSwitch
        Return
EndFunc   ;==>WM_COMMAND

Func On_WM_SYSCOMMAND($hWnd, $nMsg, $wParam, $lParam)
        Local Const $SC_CLOSE = 0xF060
        Switch BitAND($wParam, 0xFFF0)
                Case $SC_CLOSE
                        GUIDelete()
                        Exit
        EndSwitch
        Return 'GUI_RUNDEFMSG'
EndFunc   ;==>On_WM_SYSCOMMAND


最好的方式应该是hook检测窗口的消息

评分

参与人数 1金钱 +100 收起 理由
水木子 + 100 谢谢!学习了。

查看全部评分

发表于 2019-12-29 20:05:50 | 显示全部楼层
水木子 发表于 2019-12-29 19:57
是这样的,这个小程序的主要作用是,定时监测某窗口上是否出现某按钮,如果出现了则按下,$iZ += 1
如此 ...

之前编辑帖子给误删了,后来加上了
高亮的TAB间距太大了,难看
 楼主| 发表于 2019-12-29 20:07:01 | 显示全部楼层
本帖最后由 水木子 于 2019-12-29 20:09 编辑
zghwelcome 发表于 2019-12-29 20:03
最好的方式应该是hook检测窗口的消息

嗯!这个方法我有想过,但是没有成功。故出此下策。
谢谢!前辈的思路,感激不尽。
 楼主| 发表于 2019-12-29 20:25:34 | 显示全部楼层
本帖最后由 水木子 于 2019-12-29 20:30 编辑
afan 发表于 2019-12-29 20:05
之前编辑帖子给误删了,后来加上了
高亮的TAB间距太大了,难看

前辈这个方法我之前有想过,但是我一直以为循环中有 Sleep 会影响 GUIRegisterMsg 的相应速度,所以就没有继续往下深入,经测试是可行的,看来我要对 GUIRegisterMsg 重新审视了,谢谢!

另外不得不佩服前辈写代码的速度,可以说已经达到了信手拈来的地步,我的帖子刚开,前辈立即跟上。思路与代码也随之跟上,可见神速!佩服,佩服!


发表于 2019-12-29 21:57:46 | 显示全部楼层
水木子 发表于 2019-12-29 20:25
前辈这个方法我之前有想过,但是我一直以为循环中有 Sleep 会影响 GUIRegisterMsg 的相应速度,所以就没 ...

木子过奖了哦  这不也是在你的代码和思路上改的吗  各有千秋罢了~
zghwelcome 的方法也不错,只是个人偏好尽量独立函数化处理完成,尽量少与系统消息挂钩,系统消息我一般只处理主脚本的事件。当然这里只是个小脚本用不着想太多,习惯使然~
发表于 2020-1-13 16:47:35 | 显示全部楼层
水木子 发表于 2019-12-29 19:57
是这样的,这个小程序的主要作用是,定时监测某窗口上是否出现某按钮,如果出现了则按下,$iZ += 1
如此 ...

我也写过这样一个守护程序,其中循环时的退出,用的热键。

其他的就是循环,在循环中设置几个全局数组,当做触发时机。

您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-12-23 16:17 , Processed in 0.079224 second(s), 20 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表