找回密码
 加入
搜索
查看: 6024|回复: 9

[效率算法] 如何中断程序[已解决]

  [复制链接]
发表于 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
发表于 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
 楼主| 发表于 2013-3-17 22:22:36 | 显示全部楼层
回复 2# afan


    Afan 谢谢解答,不过我的程序肯定不是这么多sleep,甚至没有sleep。我只是为了方便描述问题,随便写了一个代码。我是想找一个通用的办法,比如我的代码中的这个start函数可能有几千行,里面没有sleep,并且不一定都有规律的是一个操作,所以我想随时中断,回到while 1。
发表于 2013-3-17 22:29:10 | 显示全部楼层
本帖最后由 afan 于 2013-3-17 22:32 编辑
回复  afan


    Afan 谢谢解答,不过我的程序肯定不是这么多sleep,甚至没有sleep。我只是为了方便描 ...
haijie1223 发表于 2013-3-17 22:22



    要把一个已经在运行的函数中止(函数返回,并非直接退出程序),应该只能在函数中适当的位置增加判断,来作出是否应该即时返回的动作。
就以上的例子为例,就算没有Sleep,也没用规则的执行动作,只需在合适的位置增加“If $STFlag Then Return”行即可。

评分

参与人数 1金钱 +30 贡献 +2 收起 理由
haijie1223 + 30 + 2 谢谢!

查看全部评分

 楼主| 发表于 2013-3-17 22:37:30 | 显示全部楼层
回复 4# afan


    谢谢Afan!
发表于 2013-3-17 23:43:25 | 显示全部楼层
回复 2# afan

刚开始还担心这种中断方式是否会导致test函数没有返回,资源没有释放。于是改造Func test(),开始定义Dim $aTemp[100],然后去测试看内存占用会不会增加。发现除了首次点击,后续反复操作占用内存并不明显增加。看来这种中断方式似乎没有造成test函数不返回,资源不释放的现象。
发表于 2013-3-20 13:52:19 | 显示全部楼层
很实用的小技巧
发表于 2013-3-24 00:28:21 | 显示全部楼层
感谢版主的回答, 小学习了一下
发表于 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[1][2]=[ ["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
发表于 2013-7-25 21:52:08 | 显示全部楼层
我先收藏,明天去公司试试。
您需要登录后才可以回帖 登录 | 加入

本版积分规则

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

GMT+8, 2024-5-4 06:42 , Processed in 0.082618 second(s), 27 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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