如何中断程序[已解决]
本帖最后由 haijie1223 于 2013-3-17 22:38 编辑不太好描述,我用如下代码简单表达一下。
按下"start"按钮,代码在运行:
可能运行到ConsoleWrite("=2=" & @CRLF),也可能运行到ConsoleWrite("=5=" & @CRLF)...
然后按下"stop"按钮,代码立即中断当前运行的代码,回到while 1。
GUICreate("test", 200, 100)
$button1 = GUICtrlCreateButton("start", 50, 50)
$button2 = GUICtrlCreateButton("stop", 150, 50)
GUISetState()
While 1
$msg = GUIGetMsg()
Switch $msg
Case -3
Exit
Case $button1
test()
Case $button2
EndSwitch
WEnd
Func test()
Sleep(500)
ConsoleWrite("=1=" & @CRLF)
Sleep(500)
ConsoleWrite("=2=" & @CRLF)
Sleep(500)
ConsoleWrite("=5=" & @CRLF)
Sleep(500)
ConsoleWrite("=6=" & @CRLF)
Sleep(500)
ConsoleWrite("=7=" & @CRLF)
Sleep(500)
ConsoleWrite("=8=" & @CRLF)
Sleep(500)
ConsoleWrite("=9=" & @CRLF)
Sleep(500)
ConsoleWrite("=10=" & @CRLF)
EndFunc ;==>test
可以考虑注册系统消息;另外 Sleep() 长了的话容易造成程序反应迟滞~GUICreate('test', 200, 100)
$button1 = GUICtrlCreateButton('start', 50, 50)
$button2 = GUICtrlCreateButton('stop', 150, 50)
GUISetState()
Global $STFlag = False
GUIRegisterMsg(0x111, '_WM_COMMAND')
While 1
$msg = GUIGetMsg()
Switch $msg
Case -3
Exit
Case $button1
test()
Case $button2
MsgBox(0, '', 'Stop ok!')
EndSwitch
WEnd
Func test()
$STFlag = 0
If _Sleep(500) Then Return
ConsoleWrite('=1=' & @CRLF)
If _Sleep(500) Then Return
ConsoleWrite('=2=' & @CRLF)
If _Sleep(500) Then Return
ConsoleWrite('=5=' & @CRLF)
If _Sleep(500) Then Return
ConsoleWrite('=6=' & @CRLF)
If _Sleep(500) Then Return
ConsoleWrite('=7=' & @CRLF)
If _Sleep(500) Then Return
ConsoleWrite('=8=' & @CRLF)
If _Sleep(500) Then Return
ConsoleWrite('=9=' & @CRLF)
If _Sleep(500) Then Return
ConsoleWrite('=10=' & @CRLF)
EndFunc ;==>test
Func _Sleep($Times, $vDef = 10)
Local $Ts = TimerInit()
Do
Sleep($vDef)
If $STFlag Then Return True
Until TimerDiff($Ts) >= $Times
EndFunc ;==>_Sleep
Func _WM_COMMAND($hWnd, $msg, $wParam, $lParam)
If BitAND($wParam, 0x0000FFFF) = $button2 Then $STFlag = True
EndFunc ;==>_WM_COMMAND
回复 2# afan
Afan 谢谢解答,不过我的程序肯定不是这么多sleep,甚至没有sleep。我只是为了方便描述问题,随便写了一个代码。我是想找一个通用的办法,比如我的代码中的这个start函数可能有几千行,里面没有sleep,并且不一定都有规律的是一个操作,所以我想随时中断,回到while 1。 本帖最后由 afan 于 2013-3-17 22:32 编辑
回复afan
Afan 谢谢解答,不过我的程序肯定不是这么多sleep,甚至没有sleep。我只是为了方便描 ...
haijie1223 发表于 2013-3-17 22:22 http://www.autoitx.com/images/common/back.gif
要把一个已经在运行的函数中止(函数返回,并非直接退出程序),应该只能在函数中适当的位置增加判断,来作出是否应该即时返回的动作。
就以上的例子为例,就算没有Sleep,也没用规则的执行动作,只需在合适的位置增加“If $STFlag Then Return”行即可。 回复 4# afan
谢谢Afan! 回复 2# afan
刚开始还担心这种中断方式是否会导致test函数没有返回,资源没有释放。于是改造Func test(),开始定义Dim $aTemp,然后去测试看内存占用会不会增加。发现除了首次点击,后续反复操作占用内存并不明显增加。看来这种中断方式似乎没有造成test函数不返回,资源不释放的现象。 很实用的小技巧 感谢版主的回答, 小学习了一下 提供 一個更容易理解的 範例 官方網站的範例
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
; Set a HotKey
HotKeySet("x", "_Interrupt")
; Declare a flag
$fInterrupt = 0
$hGUI = GUICreate("Test", 500, 500)
$hButton_1 = GUICtrlCreateButton("Func One", 10, 10, 80, 30)
$hButton_2 = GUICtrlCreateButton("Func Two", 10, 50, 80, 30)
; Create a dummy control for the Accelerator to action when pressed
$hAccelInterupt = GUICtrlCreateDummy()
; Set an Accelerator key to action the dummy control
Dim $AccelKeys=[ ["z", $hAccelInterupt] ]
GUISetAccelerators($AccelKeys)
GUISetState()
; Intercept Windows command messages with out own handler
GUIRegisterMsg($WM_COMMAND, "_WM_COMMAND")
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
Exit
Case $hButton_1
_Func_1()
Case $hButton_2
_Func_2()
EndSwitch
WEnd
Func _Func_1()
; Make sure the flag is cleared
$fInterrupt = 0
For $i = 1 To 20
ConsoleWrite("-Func 1 Running" & @CRLF)
; Look for the flag
If $fInterrupt <> 0 Then
; The flag was set
Switch $fInterrupt
Case 1
ConsoleWrite("!Func 1 interrrupted by Func 2" & @CRLF)
Case 2
ConsoleWrite("!Func 1 interrrupted by HotKey" & @CRLF)
Case 3
ConsoleWrite("!Func 1 interrrupted by Accelerator" & @CRLF)
EndSwitch
Return
EndIf
Sleep(100)
Next
ConsoleWrite(">Func 1 Ended" & @CRLF)
EndFunc
Func _Func_2()
For $i = 1 To 3
ConsoleWrite("+Func 2 Running" & @CRLF)
Sleep(100)
Next
ConsoleWrite(">Func 2 Ended" & @CRLF)
EndFunc
Func _Interrupt()
; The HotKey was pressed so set the flag
$fInterrupt = 2
EndFunc
Func _WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
; The Func 2 button was pressed so set the flag
If BitAND($wParam, 0x0000FFFF) =$hButton_2 Then $fInterrupt = 1
; The dummy control was actioned by the Accelerator key so set the flag
If BitAND($wParam, 0x0000FFFF) =$hAccelInterupt Then $fInterrupt = 3
Return $GUI_RUNDEFMSG
EndFunc ;==>_WM_COMMAND 我先收藏,明天去公司试试。
页:
[1]