haijie1223 发表于 2013-3-17 20:45:18

如何中断程序[已解决]

本帖最后由 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

afan 发表于 2013-3-17 21:23:27

可以考虑注册系统消息;另外 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

haijie1223 发表于 2013-3-17 22:22:36

回复 2# afan


    Afan 谢谢解答,不过我的程序肯定不是这么多sleep,甚至没有sleep。我只是为了方便描述问题,随便写了一个代码。我是想找一个通用的办法,比如我的代码中的这个start函数可能有几千行,里面没有sleep,并且不一定都有规律的是一个操作,所以我想随时中断,回到while 1。

afan 发表于 2013-3-17 22:29:10

本帖最后由 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”行即可。

haijie1223 发表于 2013-3-17 22:37:30

回复 4# afan


    谢谢Afan!

mbdnmt 发表于 2013-3-17 23:43:25

回复 2# afan

刚开始还担心这种中断方式是否会导致test函数没有返回,资源没有释放。于是改造Func test(),开始定义Dim $aTemp,然后去测试看内存占用会不会增加。发现除了首次点击,后续反复操作占用内存并不明显增加。看来这种中断方式似乎没有造成test函数不返回,资源不释放的现象。

wql8549 发表于 2013-3-20 13:52:19

很实用的小技巧

w58850 发表于 2013-3-24 00:28:21

感谢版主的回答, 小学习了一下

kk_lee69 发表于 2013-5-18 10:38:47

提供 一個更容易理解的 範例   官方網站的範例


#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

jabilyang 发表于 2013-7-25 21:52:08

我先收藏,明天去公司试试。
页: [1]
查看完整版本: 如何中断程序[已解决]