找回密码
 加入
搜索
查看: 64139|回复: 83

Autoit里用多进程模拟多线程

 火... [复制链接]
发表于 2008-5-10 23:10:39 | 显示全部楼层 |阅读模式
一直以来Autoit都不支持多线程,因此一些需要同时运行多个循环的操作也就无法实现。这个问题在其它的某些语言里也经常出现,解决的方法就是使用多进程。

所谓多进程,就是同时运行多个子进程,每个子进程负责不同的操作,藉此达到和多线程相当的效果。Autoit本身已经具备了实现多进程的条件,且已经有人完成了相关的自定义函数。下面我将具体讲解如何利用这些自定义函数实现多进程。

首先到 http://www.autoitscript.com/foru ... 29326&hl=CoProc 下载CoProc.zip,压缩包里的CoProc.au3包含了实现多进程的相关函数,你可以把这个文件复制到Include目录下。

函数使用说明:

_CoProc() 这个函数的作用是启动自己的子进程,然后执行指定的函数。比方说如果你想另开一个进程执行“fuck”函数,代码写_CoProc("fuck")就行了。这个函数会返回子进程的PID,在对子进程进行操作时会用到这个PID。另外,你可以无限制开启子进程,且每个子进程都可以建立完全独立的GUI。

_ProcSuspend() & _ProcResume() 暂停/恢复进程。如果你开了一个子进程专门下载文件,就可以利用这两个函数暂停/继续下载。范例:_ProcSuspend(@PID) 。

_CloseHandle() 关闭子进程。范例:_CloseHandle(@PID) 。

_CoProcSend() 向指定进程发送消息。当子进程有新的信息(比如完成下载)需要提示母进程时,就可以使用这个函数。范例:_CoProcSend($PID, "发送的消息内容")。

_CoProcReciver() 注册一个函数用于接收其他进程用_CoProcSend函数传递过来的消息,每当收到消息时注册的函数就会被执行。需要注意的是,被注册的函数必须有且只有一个自定义参数,而传递的参数里就是发送过来的消息。范例:_CoProcReciver("函数名称")。

例子:
#NoTrayIcon
#include "CoProc.au3"

#region 主程序区域
#include <GUIConstants.au3>
$Form1 = GUICreate("Multiple File Download", 622, 119, 192, 125)
GUICtrlCreateLabel("http://www.mv.com/test/paths.txt (1Mb)", 8, 8)
GUICtrlCreateLabel("http://support.shaw.ca/troubleshooting/files/download.dat (20Mb)", 8, 48)
$Progress1 = GUICtrlCreateProgress(8, 24, 601, 17)
$Progress2 = GUICtrlCreateProgress(8, 64, 601, 17)
$Button1 = GUICtrlCreateButton("Pause", 8, 88, 81, 25)
$Button2 = GUICtrlCreateButton("Resume", 96, 88, 81, 25)

$iPidSmall = _CoProc("Small") ;开启子进程,子进程将执行Small()函数,$iPidSmall得到的是子进程的PID
$iPidBig = _CoProc("Big")
GUISetState(@SW_SHOW)

_CoProcReciver("Reciver") ;注册Reciver()函数来接收子进程传递过来的消息

While 1
    $msg = GuiGetMsg()
    Select
    Case $msg = $GUI_EVENT_CLOSE
        ExitLoop
    Case $msg = $Button1
          _ProcSuspend($iPidSmall) ;暂停$iPidSmall这个子进程
          _ProcSuspend($iPidBig)
    Case $msg = $Button2
          _ProcResume($iPidSmall) ;恢复$iPidSmall子进程
          _ProcResume($iPidBig)
    Case Else
        ;
    EndSelect
WEnd
FileDelete(@TempDir & "\smalltest.tmp")
FileDelete(@TempDir & "\bigtest.tmp")
Exit

Func Reciver($vParameter)
    ;$vParameter里就是子进程发来的消息
    $aParam = StringSplit($vParameter,"|")
    If $aParam[1] = "small" Then GUICtrlSetData($Progress1,$aParam[2])
    If $aParam[1] = "big" Then GUICtrlSetData($Progress2,$aParam[2])
EndFunc
#endregion  

#region Small()函数里是'Small file'子进程的所要执行的代码
Func Small()
    $url = "http://www.mv.com/test/paths.txt"
    $size = InetGetSize($url)
    InetGet($url,@TempDir & "\smalltest.tmp",1,1)
    While @InetGetActive And ProcessExists($gi_CoProcParent)
        ;在下载时不断向父进程发送下载进度,$gi_CoProcParent是父进程的PID,这个变量是函数自己建立的
          _CoProcSend($gi_CoProcParent,"small|" & Round(@InetGetBytesRead / $size * 100,0))
        Sleep(250)
    WEnd
      _CoProcSend($gi_CoProcParent,"small|100")
EndFunc
#endregion

#region 'Big file'子进程执行的代码
Func Big()
    $url = "http://support.shaw.ca/troubleshooting/files/download.dat"
    $size = InetGetSize($url)
    InetGet($url,@TempDir & "\bigtest.tmp",1,1)
    While @InetGetActive And ProcessExists($gi_CoProcParent)
          _CoProcSend($gi_CoProcParent,"big|" & Round(@InetGetBytesRead / $size * 100,0))
        Sleep(250)
    WEnd
      _CoProcSend($gi_CoProcParent,"big|100")
EndFunc
#endregion
注意事项:
子进程发送消息时需要母进程的PID,而母进程的PID储存在$gi_CoProcParentli里
子进程可以正常使用脚本里的所有自定义函数
在子进程执行的那个函数里你不能再#include函数库或是用Func定义函数
对一个子进程不要重复使用_ProcSuspend()和_ProcResume() 函数,否则会让子进程无响应

——END——

评分

参与人数 3金钱 +4 收起 理由
bill-0970 + 2 不错!
starl + 1
kakinkgb + 1

查看全部评分

发表于 2012-2-29 20:20:51 | 显示全部楼层
很不错,已经实现,不过_CoProcSend()函数不起作用。必须到http://www.autoitscript.com/foru ... amp;attach_id=33753
下载新的CoProc.au3,覆盖Include中的文件

Posted 17 April 2011 - 09:38 AM

Here's CoProc.au3 with _CoProcSend and _DuplicateHandle fixed.
Attached Files
  CoProc.au3   23.6K   159 downloads
发表于 2008-5-25 23:29:06 | 显示全部楼层
这个很牛啊,我也试着做了个
#include "CoProc.au3"
while 1
$Pidmsgb = _CoProc("msgb")
sleep(3000)
wend
func msgb()
        msgbox(0,'test','test',5)
endfunc

另外,我的au3版本是3.2.11.10 ,必须把49行和64行注释掉才能运行

评分

参与人数 1金钱 +5 收起 理由
qop1830 + 5 拿去买糖吧!!

查看全部评分

发表于 2008-5-26 11:48:59 | 显示全部楼层
这个好。收藏着用了。
发表于 2008-5-29 22:53:26 | 显示全部楼层
_CoProc("fuck")


Removed: RunErrorsFatal option ( Opt() ).
不知道版本里改怎么弄


看了2楼的回答我明白了




[ 本帖最后由 qop1830 于 2008-5-29 23:03 编辑 ]

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2008-7-12 11:39:11 | 显示全部楼层
谢谢楼主和2楼,太谢谢了,呜.......
发表于 2008-8-4 18:14:52 | 显示全部楼层
CoProc.zip没得下载了
发表于 2009-2-7 10:07:37 | 显示全部楼层
貌似_CloseHandle不起作用呀,我用它关闭进程,结果都关不掉。
发表于 2009-5-13 09:10:02 | 显示全部楼层
好东西,珍藏
发表于 2009-6-2 12:00:11 | 显示全部楼层
_CloseHandle不起作用啊
发表于 2009-6-5 03:59:42 | 显示全部楼层
_CoProcSend(Bug(), $var1 ,$var2 , $var3 ,$var4)      ;传递4个参数就不可以了
_CoProcSend(Bug(), $var1 ,$var2 , $var3 )      ;传递3个参数可以
好郁闷呀~~~~!!!!不知道应该怎么处理
发表于 2009-6-5 07:42:30 | 显示全部楼层
这玩意不错,得留个名
发表于 2009-6-6 03:34:19 | 显示全部楼层
发表于 2009-6-12 10:57:52 | 显示全部楼层
似乎比较高深啊,慢慢看
发表于 2009-6-18 00:46:36 | 显示全部楼层
这个很牛啊,我也试着做了个
#include "CoProc.au3"
while 1
$Pidmsgb = _CoProc("msgb")
sleep(3000)
wend
func msgb()
        msgbox(0,'test','test',5)
endfunc

另外,我的au3版本是3.2.11.10 ,必须 ...
kakinkgb 发表于 2008-5-25 23:29


是的,我的修改就可以了...谢谢啊
发表于 2009-6-20 23:52:43 | 显示全部楼层
这个比多线程好,AU3中用SETTIMER模拟多线程常会莫名的阻塞,根本得不到执行
您需要登录后才可以回帖 登录 | 加入

本版积分规则

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

GMT+8, 2024-12-23 04:23 , Processed in 0.096364 second(s), 28 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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