TC官方合作论坛

 找回密码
 立即注册
查看: 1962|回复: 3

[学习心得] (辅助不再崩溃系列)多线程之事件机制与线程.等待 一进一出

[复制链接]
发表于 2014-10-8 00:43:50 | 显示全部楼层 |阅读模式

马上加入TC

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
本帖最后由 裤裆里面有杀气 于 2014-10-8 00:43 编辑

==========项目名称: 事件机制与线程.等待() 之一进一出^_^  ==========
>保存所有文档
>开始编译...
>编译资源文件...
>代码编译成功
>开始生成...
>开始打包附件...
>打包源文件
>打包资源文件
>附件打包完成
>D:\project\TC\事件\生成\事件.exe 生成成功
程序暂停在 38 行         文件:d:\project\tc\事件\事件\事件.t
  事件对象句柄 = 线程.创建事件(真,假,"事件测试ID")
程序暂停在 39 行         文件:d:\project\tc\事件\事件\事件.t
  线程句柄1= 线程.开启("事件.检验是否出现验证码","")//开启检测线程
程序暂停在 40 行         文件:d:\project\tc\事件\事件\事件.t
  线程句柄2= 线程.开启("事件.检测人物属性","")//开启检测线程
程序暂停在 41 行         文件:d:\project\tc\事件\事件\事件.t
  事件.登陆游戏() // 登陆处理


输出>>"A"          行号:14 文件:d:\project\tc\事件\事件\事件.t


输出线程1里面的A,而没有输出等待.事件(-1)后面的"Aa",说明进入了一次线程.
但是在因为是未触发状态,线程.等待(),会被挂起等待信号


程序暂停在 6 行         文件:d:\project\tc\事件\事件\事件.t
这里第六行是登陆游戏函数
功能 登陆游戏()
// 以下代码省略
traceprint("Login Game")
  辅助.等待(100)
  调试输出("已经登陆成功!")
  返回 0
功能结束


输出>>"B"          行号:27 文件:d:\project\tc\事件\事件\事件.t


输出线程2里面的B,而没有输出等待.线程.等待()后面的"Bb",说明进入了一次线程.
但是在因为是未触发状态,线程.等待(),会被挂起等待信号




程序暂停在 8 行         文件:d:\project\tc\事件\事件\事件.t
第八行代码:traceprint("Login Game")


T友们,到了这里,但凡有点理智的人,都应该明白.在进入登陆游戏(),函数前两个线程已经启动,然而因为是未触发状态
所以 线程.等待()被挂起.后面的代码,目前不会被执行.


TC文档:
bInitialState:事件初始状态,如下所示
真 事件初始化为可调度状态(可用,线程.等待()可以往后执行,不会挂起)
假 事件初始为未触发状态(不可用,线程.等待()会挂起,等待信号为可用状态,才能往后执行)


那么我们继续向下单步.


输出>>"Login Game"          行号:8 文件:d:\project\tc\事件\事件\事件.t
程序暂停在 9 行         文件:d:\project\tc\事件\事件\事件.t
程序暂停在 10 行         文件:d:\project\tc\事件\事件\事件.t
输出>>"已经登陆成功!"          行号:10 文件:d:\project\tc\事件\事件\事件.t
程序暂停在 11 行         文件:d:\project\tc\事件\事件\事件.t




  线程.等待(线程句柄1,60*1000)//最长等待线程句柄1的线程执行1分钟
  线程.等待(线程句柄2,60*1000)//最长等待线程句柄2的线程执行1分钟




程序暂停在 42 行         文件:d:\project\tc\事件\事件\事件.t


我们看42行代码.


线程.设置事件(事件对象句柄) // 设置事件为可调度状态,激活2个检测线程 .


函数空间: 中文:线程
英文:thread
函数描述: 设置事件为可调度状态(可用,线程.等待()可以往后执行,不会挂起)
函数原型: 设置事件(handle)
setevent(handle)
        这一行代码执行后,各线程等待()函数已经变成可调用状态,继续向下.
但是程序目前在单步状态,代码还没有返回,所以我们在线程里面的"Aa"和"Bb"特征码没有被输出




程序暂停在 44 行         文件:d:\project\tc\事件\事件\事件.t


线程.等待(线程句柄1,60*1000)//最长等待线程句柄1的线程执行1分钟


等待线程执行时间,这个意思就是说,如果这个线程函数,
执行时间超过一分钟,还没有返回,那就不在等待他,直接向下执行了.
好, 事件的设置、重置机制,我们看了一个大概.
我们知道,线程在开启的时候,进入了一次线程,但是因为我们事件状态创建的时候,设置为未触发.所以
线程.等待 是挂起的.不会向下执行.


那么下面,我们深入分析线程.等待,这个函数里面的小秘密.


-------------------------------------------我是分割线----------------------------------------
        我们把线程A里面的代码,改成这样,再重置时间后,睡10秒,然后再执行


功能 检验是否出现验证码()
    traceprint("A")
// 开启线程之后就挂起线程等待事件
  线程.等待(事件对象句柄,-1)
   traceprint("Aa")
  线程.重置事件(事件对象句柄)// 手动重置事件
  help.sleep(10000)
  traceprint("十秒过后")
// 以下代码省略
  调试输出("检测验证码的线程被激活!")
  返回 0
功能结束


//再把线程等待时间改为,1秒.
线程.等待(线程句柄1,1000)


见证奇迹的时刻来临了.(..咳咳,此刻 佐助变身,EZ九尾狐灵魂附体^_^)




输出>>"Aa"          行号:17 文件:d:\project\tc\事件\事件\事件.t
输出>>"Bb"          行号:30 文件:d:\project\tc\事件\事件\事件.t
输出>>"检测人物属性的线程被激活!"          行号:33 文件:d:\project\tc\事件\事件\事件.t






调试输出(日期时间.当前日期())
先获得一次时间


输出>>"2014/10/7 23:47:24"          行号:43 文件:d:\project\tc\事件\事件\事件.t
这里的时间 24秒




我们只等待一秒.看是否会返回,还是线程等待后返回


线程.等待(线程句柄1,1000)//等待一秒
调试输出(日期时间.当前日期())
调试输出("我是 线程.等待(线程句柄1,1000) 下面一句")


输出>>"2014/10/7 23:47:25"          行号:45 文件:d:\project\tc\事件\事件\事件.t
输出>>"我是 线程.等待(线程句柄1,1000) 下面一句"          行号:46 文件:d:\project\tc\事件\事件\事件.t

相差一秒,确定线程.等待()只会等待设定的时间,不管线程有没有执行完毕






  线程.等待(线程句柄2,60*1000)//最长等待线程句柄2的线程执行1分钟
  线程.关闭句柄(事件对象句柄) // 释放事件
  调试输出("程序执行完毕")




输出>>"程序执行完毕"          行号:49 文件:d:\project\tc\事件\事件\事件.t
输出>>"十秒过后"          行号:20 文件:d:\project\tc\事件\事件\事件.t
输出>>"2014/10/7 23:47:34"          行号:21 文件:d:\project\tc\事件\事件\事件.t
输出>>"检测验证码的线程被激活!"          行号:23 文件:d:\project\tc\事件\事件\事件.t



我们可以看出来.程序执行完毕后,过了十秒.线程函数,才执行完毕.





这里是线程1里面的调试输出
  help.sleep(10000)
  traceprint("十秒过后")
    调试输出(日期时间.当前日期())


-------------------------------------------邪恶分割线-----------------------------------------

此次代码单步调试,我觉得能让大家更直观的明白"事件机制"整个响应过程.
我们写代码,以后要注意几个方面:
1.线程的功能语句要写到等待事件后面,否则在开启线程后,会被执行,如果多线程同时操作某个全局数据,可能会出错.
如果是专门为做的一些特殊操作而把代码写在,线程.等待()前,要特别注意同步的问题,当然局部变量,请无视...
2.一定记得,手动重置事件,把线程状态调整为未触发.
否则,后面如果再次开启线程,线程.等待()直接为可用状态.
会造成例如:A功能语句还没执行完必要的操作,线程函数就开始了,数据又果断不同步了.

3.因为顺序执行的原因,如果后面代码会用到前面线程中的数据,一定要考虑线程执行时间问题.




好的.此次的分析,已经到了尾声.!


那么问题来了.!!!!!
学习一进一出技术哪家强?
当然是,官方学院EZ啊!!!.
哈哈哈.!




回复

使用道具 举报

 楼主| 发表于 2014-10-8 01:25:16 | 显示全部楼层
本帖最后由 裤裆里面有杀气 于 2014-10-8 01:35 编辑

白话版 创建事件 函数解释

创建事件函数


bManualReset: 事件是否自动重置

bManualReset=真

"概念"
自动重置事件:因为事件不可调度的原因,在多个线程都被挂起等待的时候,一旦程序事件被设置为可调度状态之后,系统会激活多个挂起线程中的一个线程继续执行,而其他线程继续等待,直到下次事件被设置为可调度状态

详解:
1.只有一个正在等待该事件的线程会得到信号变成可调度状态,
"事件状态"是通过操作系统把"事件信号"调度给任何一个"等待中的线程",
这个"等待中的线程"是指线程函数必须执行了线程.等待()的函数而且同一时间只有一个线程得到.


2.然后系统立即自动把对象信号置为不可用状态,其他调用线程.等待()的线程会挂起.

3.当信号再次变为可用状态,当然上一个得到信号的线程函数,得调用 线程.设置事件()才能将事件信号设为可用状态,然后其他线程才能等待到信号,然后才能从它们的线程.等待()语句处,继续向后执行.

4."自动重置"不需要调用,线程.重置事件()来重置状态,因为系统在每次 线程.等待()后会自动重置事件为未触发状态




bManualReset=假
"概念"
手动重置: 因为事件不可调度的原因,在多个线程都被挂起等待的时候,一旦程序事件被设置为可调度状态之后,所有线
程被激活继续执行

详解:
1.正在等待该事件的所有线程将会变成可调度状态,且事件状态由用户自己设置.
2.调用 线程.重置事件()将事件设置为不可调度状态.
3.调用 线程.设置事件()设置事件为可调度状态.


bInitialState:事件初始状态

真 事件初始化为可调度状态(可用,线程.等待()可以往后执行,不会挂起)


假 事件初始为不可调度状态(不可用,线程.等待()会挂起,等待信号为可用状态,才能往后执行)


eventName: 事件名,在别的进程中可以通过事件名打开该事件对象






回复 支持 反对

使用道具 举报

发表于 2014-10-8 10:55:41 | 显示全部楼层
学习学习~~~顺便巧摸4楼狗头
回复 支持 反对

使用道具 举报

发表于 2014-10-9 12:19:17 | 显示全部楼层
嗯~~~此番描述,果然跌宕起伏一波三折,给人以无限的想象空间,打斗场面浩大华丽而不显庸俗,特别是对于人物招式及感受的象声描写,更能引人遐想。真乃神作也!!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条

关闭

小黑屋|TC官方合作论坛 (苏ICP备18045623号)

GMT+8, 2024-5-19 01:45 , Processed in 0.045874 second(s), 22 queries .

Powered by 海安简单软件服务部

© 2008-2019 版权所有 保留所有权利

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