版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、多线程同步操作多个窗口RunApp notepad.exeRunApp notepad.exeRunApp notepad.exeDelay 2000Dimenv temp_Hwndtemp_Hwnd = 0Dim str, arr, istr = Plugin.Window.Search(无标题-记事本)arr = Split(str, |)For i = 0 To UBound(arr) - 1temp_Hwnd = Plugin.Window.FindEx(arr(i), 0, Edit, 0)BeginThread WriteStringWhile temp_Hwnd 0判断多线程已经
2、启动完毕,继续循环下一个。Delay 500WendNextEndScriptFunction WriteString()Dim str, HwndHwnd = temp_Hwndtemp_Hwnd = 0Dostr = WaitKeyIf Hwnd Plugin.Window.GetKeyFocusWnd ThenCall Plugin.Bkgnd.KeyPress(Hwnd, str)End IfLoopEnd Function多线程多开窗口同步执行与子线程间的数值如何传递:Dimenv isThread, iDim arr_Thread()For i = 0 To 2IsThread =
3、 False未启动线程Redim Preserve arr_Thread(i)arr_Thread(i) = BeginThread(EnterThread)While IsThread = False未启动成功,等待中Delay 500Wend跳出循环说明isThread = True,已经执行到了,循环继续启动下一个EndScript结束主线,但子线程还会继续运行函数调用/Function EnterThread() TOC o 1-5 h z Dim nn = iIsThread = TrueDoTracePrint 运行线程:& nDelay 500LoopEnd Function多线
4、程运行中单独停止某个子线程演示:环境变量声明Dimenv Hwnd, IsThreadIsThread = FalseDoHwnd = Plugin.Window.Find(Notepad,无标题-记事本)If Hwnd = 0 ThenRunApp notepad.exe : Delay 2000TracePrint 运行记事本End IfLoop While Hwnd = 0获得记事本中输入子窗口句柄,以便按键输入内容Hwnd = Plugin.Window.FindEx(Hwnd, 0, Edit, 0)全局变量声明Dim IdThread主循环JDoIf WaitKey() = 81
5、ThenIf IsThread = False ThenIdThread = BeginThread(WriteString)DoDelay 500Loop While isThread = FalseTracePrint线程启动成功!”ElseTracePrint线程停止操作!”StopThreadidThreadisThread =FalseEnd ifEnd if TOC o 1-5 h z Loop以下是函数区域Function WriteString()isThread = TrueDoCall Plugin.Bkgnd.KeyPress(Hwnd, 65)Delay 500Loop
6、End Function主线程逐个开启子线程五开操作演示:五开操作Dim str_Hwndstr_Hwnd = vbNullString记录都有哪些窗口句柄在运行DimEnv isHwndisHwnd = 0For i_win = 0 To 4DoRunApp notepad.exestr = Plugin.window.Search(无标题-记事本)arr = Split(str, |)if str vbNullStringThenFor i = 0 To UBound(arr) - 113.if inStr(str_Hwnd, arr(i) = 0 Then14.isHwnd = arr(
7、i)str_Hwnd = str_Hwnd & arr(i) & |Exit ForEnd IfNextElseIsHwnd = arr(0)End IfLoop While IsHwnd = 0Call Plugin.Window.SetClientSize(IsHwnd, 300, 300)CallPlugin.Window.Move(IsHwnd, 300 * i_win, 0)BeginThread 后台喊话DoDelay 1000LoopUntil Hwnd = 0NextEndScriptFunction 后台喊话()Dim HwndHwnd =Plugin.Window.Find
8、Ex(IsHwnd, 0, Edit, 0) TOC o 1-5 h z IsHwnd=0DoCall Plugin.Bkgnd.SendString(Hwnd,文字测试)Call Plugin.Bkgnd.KeyPress(Hwnd, 13)Delay 500LoopEnd Function一、多线程是什么,可以干什么一般来说,我们编写的脚本都是一条道走到黑,最多加点循环、判断和跳转,程序始终是按部就班 的执行指定的命令,只能同时干一件工作,让它取色就取色,让它单击就单击,不能同时完成两项以上的 工作。多线程的出现,是让脚本可以同时开展几项工作,在单击时,可以通过环境变量传过来取色子程序 获
9、得的坐标,而无需在每次单击命令前执行调用取色子程序。当然这只是一个很简单的例子,像这样简单 的情况,是没必要弄个多线程的,如果非要弄出多线程处理,反而要考虑到同步的问题:这边要单击了,那边取色命令传过来的坐标值,是多长时间以前的?或者直接取色命令还没执行完,这边到底单击哪里 呢?有人说按键精灵的多线程是伪多线程,其实不管是真假多线程,对于电脑的CPU来说,同时只会做一 件事情,只是说把各个线程传过来需要处理的东西按照时间先后和优先级的关系,排个队列挨个执行而已。 就像你去食堂打饭,很多人排队打,但是打饭的师傅只有一个,关系好的可能能插个队。多核CPU大概是 食堂有好几个窗口,这样的话,倒是有可
10、能同时有几个同学在打饭。那么,我们假设要做的工作是让一个 寝室的同学聚餐,可以派一个人去打饭(单线程),或者派几个人去打饭(多线程)。假设班长下达了命 令:甲负责打菜,乙负责打饭,丙负责买汽水,其余的负责准备场地,那么什么时候开饭,应该要等到甲 乙丙任务都完成了才行。可以约定时间,也可以让每个人报告。如果有一辆自行车可以用,那么甲乙丙三 个人都可以骑,同时骑,也就相当与出现了三辆,谁的骑坏了都与别人的没关系。为了更好更快的完成人 物,甲乙丙三人都可以同时拉剩下的人帮忙,比如丁,也会变成三个人,每个丁分身都与其他分身无关。 好吧,不闲扯了,代码也不多贴,把我总结的规律直接写出来吧。(一)首先要弄
11、明白变量的作用域这个问题:在按键里,有这些规律:在主体代码最前面(最好这么干,你非要在中间写一句dim,我也没办法)用dim定义的变量(统 称外部变量),作用范围为全脚本,但是如果在子程序里面出现用dim显式定义的同名变量或者在子程序 参数列表里的同名变量,那么在该子程序体内所用到的该变量,是内部变量,与外部变量无关;子程序中可以用dim关键字定义内部变量,如果未定义的变量直接使用,默认为外部变量。外部变量如果出现在子程序中,并且子程序中没有定义过同名的内部变量,在正常的调用中,按外 部变量处理,但是如果在多线程中调用这个子程序,那么该变量会自动变成内部变量初始化掉,具体情况 如下:Dim a
12、/此处是否定义对多线程内部的变量a无影响BeginThread cdSub cdDim a/此处如果定义了,变量a为子程序cd的内部变量,/否则如果此处为定义,且子程序cs中未定义,则变量a为整个多线程的外部变量a = 23Call cs(a)TracePrint aCall cs(a)TracePrint aEnd SubSub cs(b)Dim a/此处如果定义了,变量a在子程序cs内部永远都是内部变量/或者把b改成a,也是隐式的定义了一个内部变量aa=a+b复制代码在主题代码最前面用Global定义的是全局变量,作用范围多说同DimEnv环境变量,我猜这两个有 一个可以在脚本之间交换数据
13、。如果只是用于单脚本的多线程,可以看成一样的。这两个关键字都不能出 现在子程序包括多线程的子程序中;还有个大家关心的大漠等插件的绑定问题,规律如下:Set dm = CreateObject(dm.dmsoft)/此处绑定之后,程序主体中调用的子程序都可以使用大漠插件call csBeginThread cdSub cdSet dm = CreateObject(dm.dmsoft)/此处绑定之后,此线程调用的任何子程序都可以使用大漠插件Call csEnd SubSub cshwnd = dm.GetForegroundWindow()TracePrint hwndEnd Sub复制代码通过
14、上面的归纳,更可以明确多线程基本等同与新建一个内部脚本,可以调用主脚本内的任何子程序资源, 调用方式为创建一个该子程序的副本,独立与主程序体之外。如果要在某个多线程内定义一个可以在子程 序间传递数据的变量,办法是直接给变量赋值,不要在它调用到的任何子程序中显式或者隐式的定义该变 量。如果要实现在程序主体和多线程之间传递数据,需要在程序主体的最前面用DimEnv关键字定义环境 变量。具体使用见后面的例子。(二)多线程命令解释:BeginThread同时运行过程:可以理解为开辟一块新的内存空间来运行一个任务,在该多线程子程 序中所调用的资源,统统纳入这个内存空间,如果需要与外界交换数据,必须通过D
15、imEnv定义的环境变 量来实现。为了便于控制每一个线程,调用时可以指定一个变量来保存线程ID,一般把这个变量定义为环 境变量,这样可以在主体和线程以及线程之间实现互相控制。PauseThread暂停线程运行、ContinueThread继续线程运行、StopThread停止线程运行:通过线 程ID来暂停、继续和停止一个线程,在论坛上看到一位高手用环境变量来实现了这个功能:Dimenv 控制2BeginThread 过程 1.控制=暂停689.控制=停止10EndScriptSub 过程 1.While控制=暂停Delay 50WendIf 控制=停止Thenexit SubEnd Sub复制
16、代码当然需要把这个控制代码插入到多线程子程序的循环体中来执行,也有缺点是必须运行到此处才能实现功 能。这是题外话了,灵活的用好暂停、继续功能可以让脚本变得更灵活。比如在控制人物左右行走的子程 序中,需要判断障碍物,如果X轴无变化就向上或者向下走,如果X,Y轴都没有变化就判断为卡住,执 行卡住处置程序。可以把卡住判断和处置的代码放到一个多线程中,在左右行走子程序开始时打开卡住处 置多线程并暂停,在x轴卡住时继续运行卡住处置多线程,实现上下移动并判断y轴值是否变化,如果没 有变化就向相反方向走。左右移动的子程序中设置一个按左右行走键并判断x轴无变化就等待的循环,在 退出循环时暂停卡住处置多线程。在
17、左右行走的子程序结束的时候关掉卡住处置多线程。这样通过暂停、 继续的运用,可以减少频繁的打开关闭多线程。代码如下:Dimenv x, y,线程 ID2Sub左右移动线程ID=BeginThread(障碍物判断)PauseThread 线程 IDWhile是否到底目的地=否按左右键行走调用取得人物坐标子程序if x轴无变化thenContinueThread线程 IDEnd ifwhile x轴无变化按下左右键等待一段时间松开左右键调用取得人物坐标子程序WendPauseThread 线程 IDWendStopThread 线程 IDEnd SubSub障碍物判断while True按上下键行走
18、调用取得人物坐标子程序if y轴无变化then把控制上下的键更换方向End ifwendEnd Sub复制代码3.GetThreadID得到当前线程ID:这个从按键自带的例子来看,是在退出线程事件中,用来返回退出 的线程ID,从而根据这个ID来确定是哪一个线程退出了,给该线程上绑定的例如大漠、361等插件松绑。 这个命令只有在线程结束事件或者线程内部才能返回值,如果忘记在调用时保存线程ID,可以在线程内部 使用这个命令获取自身的线程ID。二、多线程什么情况下应该使用?多线程使用的时机,大概有两种:一种是单脚本内需要控制开展多项工作,比如上面的例子,在左 右行走卡住时开启上下行走和卡住判断;另一
19、种是通过多线程的使用,实现一个脚本对多个游戏窗口的控 制,也就是多开,下面就这两种情况说说我的看法。(一)单脚本单开的多线程这个是否使用多线程得看具体的情况来定,很多时候并不一定需要多线程才能解决问题,可以通过在循环 内部插入某些判断代码来确定是否调用别的功能。例如上面的左右行走子程序,可以改成这样:Sub左右移动While是否到底目的地=否按左右键行走调用取得人物坐标子程序while x轴无变化按下左右键和上下键等待一段时间松开左右键和上下键调用取得人物坐标子程序If y轴无变化Then把控制上下的键更换方向End IfWendWendEnd Sub复制代码如此通过对控制行走代码的修改,来实
20、现绕过障碍物和卡住判断,无需调用多线程来解决问题。这样 无需考虑两个线程之间的按键同步问题和互相干扰的问题,也不要定义多个环境变量来实现数据的交换。 像一些比较复杂的脚本,需要同时开展的工作之间没有频繁的数据传递,且确实需要做到实时监控,那么 就必须使用多线程了。比如在挂机打怪的时候需要监控草药或者矿产是否出现,一定出现就暂停打怪去采 集(假设打怪时间可以暂停),采集完成后继续打怪,可以写出如下代码:dimenv 打怪 ID,采集 ID打怪 iD=BeginThread(打怪)采集 ID=BeginThread(采集)While true5.6.Wend7.EndScript8.Sub打怪9.
21、While true10.打怪11.Wend12. EndSub13. Sub采集14.Whiletrue15.判断草药是否出现16.if草药出现then17.PauseThreac打怪 id18.采集草药19.ContinueThreac打怪 id20.end If21.Wend22. End复制代码Sub当然,在使用多线程时一定要考虑到各种情况的出现,避免在打怪的过程中暂停了打怪线程,导致 采集时被怪物攻击的情况,或者采集时草药会集中出现,可以暂缓继续打怪程序,采集完成后继续找草药,确实采集完成再继续打怪,以避免频繁的继续和暂停打怪程序。(二)单脚本多开的多线程这个需要考虑的问题就更多了,
22、不提倡新手使用多线程,除了多线程不稳定的原因外,对变量作用域不明 确、对程序流程的掌握不熟练也是一个原因。单脚本多开,要能够实现对任意线程的完美控制。我曾经想 过用一个脚本实现单线程的各个游戏窗口之间的循环控制,这个思路可以用在对多线程的控制上:枚举符合要求的窗口句柄;把获得的窗口句柄保存在数组h中;对需要做的每一个后台操作,在指定句柄时,循环到数组h中的每一个成员;dim hHwndEx = Plugin.window.Search(记事本”)h = split(HwndEx, |)/假设有一个后台单击命令For i=0 to UBound (h)Call Plugin.Bkgnd.Left
23、Click(H(i), x, y)Next i复制代码在控制多线程时,需要用到用户自定义界面,把线程ID保存在用户自定义界面的控件上,然后通过按键 来实现对各个线程的完美控制。三、如何实现多线程的灵活控制?参考: HYPERLINK /thread-349064-1-1.html /thread-349064-1-1.html这个帖子只是说明了多线程控制的思路,具体实现可以这样(还是要抱怨一句:按键的自定义界面不支 持控件数组、不能动态添加list列表项,让这件事情变得很难办了):先按照上图在自定义界面上弄5个文本框(用于手动写入线程标识,可以用角色名等区分,面对自己 都搞不清哪个是哪个了)、5个单选按钮(用于保存线程ID和选定线程,如果想同时控制多个线程可以改 成用复选框)、3个按钮(名称分别为ButtonPause、ButtonContinue、ButtonStop,用于操作选定线程), 然后编写如下脚本:DimEnv 线程 IDDim ii=1While key 123key=GetLastKey
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 如何高效报送网络舆情 2024(方法+流程)
- 机房搬迁方案
- 微积分 第3版 课件 2.5 函数的连续性
- 坪山区七年级上学期语文期末考试试卷
- 讲述京东课件教学课件
- 股东合同范本(2篇)
- 南京航空航天大学《多元统计分析》2022-2023学年第一学期期末试卷
- 南京工业大学浦江学院《数字图形设计》2022-2023学年第一学期期末试卷
- 独坐敬亭山说课稿
- 南京工业大学浦江学院《领导科学》2023-2024学年第一学期期末试卷
- 电大财务大数据分析编程作业2
- 2024年政府办事-非政府组织知识笔试参考题库含答案
- 营区物业服务投标方案(技术方案)
- 静疗相关血管解剖知识课件
- 漠河舞厅赏析
- 餐饮行业报告:中餐出海
- 2024年江苏钟吾大数据发展集团有限公司招聘笔试参考题库含答案解析
- 青少年数独智力运动会U12组数独赛前集训题
- 医院健康教育培训课件
- GH/T 1419-2023野生食用菌保育促繁技术规程灰肉红菇
- 明孝端皇后九龙九凤冠
评论
0/150
提交评论