[远航笔记流水账]易大漠多线程初级教程086(1-3)

1.易大漠多线程初级之多线程介绍

什么是多线程 没什么可说的

单线程

image

多线程

image


2.易大漠多线程初级之函数命令介绍

多线程的4个基础函数:

image

注意:

1.如果挂起失败 和恢复失败 函数会返回-1  如果成功 那么返回值肯定大于-1  用这个判断是否挂起成功

2.要关闭线程 必须是要线程_强制关闭()和线程_关闭句柄()2个函数才可以  线程_强制关闭() 是负责关闭线程 而 线程_关闭句柄() 负责把线程id这个控制线程的入口给彻底注销  我们以后再用这个线程id来控制线程都是无效的 虽然线程id内的值并没有变化

3 线程id最好是程序集 方便 其他线程操作函数的调用

4 用线程_启动脚本() 线程_挂起脚本() 线程_恢复脚本() 这是远航老师封装的 也是它推荐使用的  我们就不用精益模块的线程函数 用这几个来操作线程

5 暂时没遇到线程启动 线程强制关闭 线程关闭句柄失败的情况 就不考虑这个情况了 注意这3个函数返回为假 表示操作失败


小问题:如果没有线程 那么脚本执行期间我们无法操作界面 界面陷入假

image

如果循环没有任何延迟 运行这循环 那么界面就陷入假死 无法进行任何操作

建议:任何循环或多或少都要加入一点点延迟

避免这个情况的发声

image


小问题:有的时候 线程挂起会失败 例子里面是因为线程里面循环间隔没有 运行太快 导致的

解决办法:再循环内加入适当的延迟 同上面的问题


随便看看:老师的3个线程函数和精益模块的对应函数的区别

远航老师这里似乎是考虑到万一启动线程的线程id为空  会清理下资源? 不是很清楚干什么用

image远航image精益模块

结论:仔细看了一下  线程启动的函数 精益模块和远航老师有区别 区别就是远航的启动会考虑到玩意返回的线程id为空 会自动把线程id对应的线程资源关闭掉 而精益模块没有这个方面的应对

至于挂起和恢复函数 远航和精益模块一样 没有区别



3.1易大漠多线程初级之许可证(线程锁)应用

许可证(或者叫线程锁)作用多个线程同时使用各种共有的资源  比如全局变量 界面的各个组件总不能你抢我抢 需要指定一个规则  比如说对同一个叫intX intY的全局变量 主要是负责记录找图后的返回坐标值  如果没有规则可能出现同一时间 多个线程中的找题同时把找到的坐标写入到这个全局变量中  那么当我们要点击intX intY 里面的坐标 那么这个坐标是属于哪个线程里面的找图找到的坐标呢 会造成混乱  所以需要许可证(线程锁)规定谁先谁后 ,比如线程1来了 它把许可证放在全局变量门前 表明这个全局变量 我线程1在用 其他线程来了看到这个线程1的许可证就明白了  就在门口等  线程1使用完了全局变量后 把门口的许可证拿走了 后面的线程看到了 就纷纷把自己的许可证放到门口 争取使用权

个人感觉 许可证不能适用于大片代码 因为许可证制度是一定时间内独占 某个公共资源 其他线程都要等着 所以只在线程要使用某个公共资源的时候用一下


常见的公共资源:

1.全局变量

2.程序集变量

3界面的组件


因为老师许可证实例这部分没有录制完整 


许可证的使用注意的几点

1.许可证本身也是全局变量

2.每个线程对应一个属于它的许可证

3 定义了线程的许可证 要操作公共资源 要用进入和离开

4 线程结束 请不要忘记删除许可证

5 许可证不是万能的 在操作界面的某些组件 许可证可能也会崩溃

3.2易大漠多线程初级之许可证(线程锁)应用2

小知识:对于辅助延时()函数的理解

平时看多线程的源码 纯易语言的多线程源码  他们的基本结构

image

使用了延时()和 处理事件()配合 让循环不会导致界面陷入假死卡住状态,远航用的是 辅助延时() 看了下这个函数的源码

里面已经包含了 处理事件和延时

image


小知识:两套许可证操作函数的选择

易语言本身存在一套操作许可证的函数 参数统一要求的是整数型

.版本 2
.支持库 EThread

    创建进入许可证 ()
     进入许可区 ()
     退出许可区 ()
     删除进入许可证 ()

而远航 或者说精益模块里面的另外一套操作许可证的函数 要求参数必须是许可证类型(推荐)

.版本 2

    线程_创建许可证 ()
     线程_删除许可证 ()
     线程_进入许可区 ()
     线程_退出许可区 ()

偶得:自己练手做个简单的多线程控制 8个进度条的代码(做个纪念)

界面

image

.版本 2

.程序集 窗口程序集_启动窗口
.程序集变量 许可证集合, 线程许可证, , "0"
.程序集变量 线程id, 整数型, , "0"
.程序集变量 进度条任务, 整数型, , "0"

.子程序 __启动窗口_创建完毕

' 1. 重置进度条的位置归零
_启动窗口.进度条1.位置 = 0
_启动窗口.进度条2.位置 = 0
_启动窗口.进度条3.位置 = 0
_启动窗口.进度条4.位置 = 0
_启动窗口.进度条5.位置 = 0
_启动窗口.进度条6.位置 = 0
_启动窗口.进度条7.位置 = 0
_启动窗口.进度条8.位置 = 0

' 2.让停止按钮为灰色 开启按钮正常
_启动窗口.按钮_开启.禁止 = 假
_启动窗口.按钮_关闭.禁止 = 真
' 3. 清空编辑框的内容
_启动窗口.编辑框_日志.内容 = “”

.子程序 线程_测试函数, , 公开
.参数 当前线程标识id, 整数型
.局部变量 进度条任务标识, 整数型
.局部变量 i, 整数型

' 4 线程内 先从进度条任务数组 取到对应的进度条标识 然后开始完成进度条操作 该进度条操作完毕把日志写道编辑框里面被查看


' 3 完成上一个进度条操作 继续找下一个进度条
.判断循环首 (真)
    ' 1 从进度条任务数组获取要执行的进度条标识 如果数组为空了则直接结束线程 结束前给日志编辑框发送信息
    ' 进入许可区 (许可证集合 [当前线程标识id])
    线程_进入许可区 (许可证集合 [当前线程标识id])
    .如果 (取数组成员数 (进度条任务) < 1)
        ' 这里要写道日志编辑框里面
        跳出循环 ()

    .否则
        ' 取出数组第一个元素
        进度条任务标识 = 进度条任务 [1]
        删除成员 (进度条任务, 1, )
    .如果结束

    线程_退出许可区 (许可证集合 [当前线程标识id])
    ' 2 更具进度条标识来控制进度条进度不断增加直到500结束
    .判断开始 (进度条任务标识 = 1)
        i = _启动窗口.进度条1.位置
        .判断循环首 (i ≤ 500)
            i = i + 2
            _启动窗口.进度条1.位置 = i
            辅助延时 (50)
        .判断循环尾 ()

    .判断 (进度条任务标识 = 2)
        i = _启动窗口.进度条2.位置
        .判断循环首 (i ≤ 500)
            i = i + 2
            _启动窗口.进度条2.位置 = i
            辅助延时 (50)
        .判断循环尾 ()

    .判断 (进度条任务标识 = 3)
        i = _启动窗口.进度条3.位置
        .判断循环首 (i ≤ 500)
            i = i + 2
            _启动窗口.进度条3.位置 = i
            辅助延时 (50)
        .判断循环尾 ()

    .判断 (进度条任务标识 = 4)
        i = _启动窗口.进度条4.位置
        .判断循环首 (i ≤ 500)
            i = i + 2
            _启动窗口.进度条4.位置 = i
            辅助延时 (50)
        .判断循环尾 ()

    .判断 (进度条任务标识 = 5)
        i = _启动窗口.进度条5.位置
        .判断循环首 (i ≤ 500)
            i = i + 2
            _启动窗口.进度条5.位置 = i
            辅助延时 (50)
        .判断循环尾 ()

    .判断 (进度条任务标识 = 6)
        i = _启动窗口.进度条6.位置
        .判断循环首 (i ≤ 500)
            i = i + 2
            _启动窗口.进度条6.位置 = i
            辅助延时 (50)
        .判断循环尾 ()

    .判断 (进度条任务标识 = 7)
        i = _启动窗口.进度条7.位置
        .判断循环首 (i ≤ 500)
            i = i + 2
            _启动窗口.进度条7.位置 = i
            辅助延时 (50)
        .判断循环尾 ()

    .判断 (进度条任务标识 = 8)
        i = _启动窗口.进度条8.位置
        .判断循环首 (i ≤ 500)
            i = i + 2
            _启动窗口.进度条8.位置 = i
            辅助延时 (50)
        .判断循环尾 ()

    .默认
        ' 这里要写道日志编辑框里面
        跳出循环 ()
    .判断结束

.判断循环尾 ()

.子程序 _按钮_开启_被单击
.局部变量 i, 整数型
.局部变量 局_线程id, 整数型
.局部变量 结果, 逻辑型

' 0 按钮状态调整一下
_启动窗口.按钮_开启.禁止 = 真
_启动窗口.按钮_关闭.禁止 = 假

' 1.根据界面上的线程数量 开始生成对应的许可证
清除数组 (许可证集合)
.计次循环首 (到整数 (_启动窗口.编辑框_线程数.内容), )
    加入成员 (许可证集合, 线程_创建许可证 ())
    辅助延时 (200)
.计次循环尾 ()
' 2.生成一个进度条任务数组 每完成一个进度条 就把该进度条在数组对应的元素删除掉
清除数组 (进度条任务)
.计次循环首 (8, i)
    加入成员 (进度条任务, i)

.计次循环尾 ()
' 3 开始生成线程 并把线程对应的线程id写入到线程id数组 等待备用
清除数组 (线程id)
.计次循环首 (到整数 (_启动窗口.编辑框_线程数.内容), i)
    结果 = 线程_启动脚本 (&线程_测试函数, i, 局_线程id)
    .如果真 (结果)
        加入成员 (线程id, 局_线程id)
    .如果真结束
    辅助延时 (2000)
.计次循环尾 ()


' 4 线程内 先从进度条任务数组 取到对应的进度条标识 然后开始完成进度条操作 该进度条操作完毕把日志写道编辑框里面被查看

.子程序 _按钮_关闭_被单击
.局部变量 i, 整数型

' 改变下按钮状态
_启动窗口.按钮_开启.禁止 = 假
_启动窗口.按钮_关闭.禁止 = 真

' 清理线程
.计次循环首 (取数组成员数 (线程id), i)
    ' 线程id
    线程_强制结束 (线程id [i])
    线程_关闭句柄 (线程id [i])
    辅助延时 (200)
.计次循环尾 ()


' 删除许可证
.计次循环首 (取数组成员数 (许可证集合), i)

    ' 加入成员 (许可证集合, 线程_创建许可证 ())
    线程_删除许可证 (许可证集合 [i])
    辅助延时 (200)
.计次循环尾 ()


.子程序 __启动窗口_将被销毁
.局部变量 i, 整数型

' 清理线程
.计次循环首 (取数组成员数 (线程id), i)

    ' 线程id
    线程_强制结束 (线程id [i])
    线程_关闭句柄 (线程id [i])
    辅助延时 (200)
.计次循环尾 ()
' 删除许可证
.计次循环首 (取数组成员数 (许可证集合), i)

    ' 加入成员 (许可证集合, 线程_创建许可证 ())
    线程_删除许可证 (许可证集合 [i])
    辅助延时 (200)
.计次循环尾 ()


.子程序 _按钮_重置_被单击

.如果真 (_启动窗口.按钮_开启.禁止 = 假)
    ' 1. 重置进度条的位置归零
    _启动窗口.进度条1.位置 = 0
    _启动窗口.进度条2.位置 = 0
    _启动窗口.进度条3.位置 = 0
    _启动窗口.进度条4.位置 = 0
    _启动窗口.进度条5.位置 = 0
    _启动窗口.进度条6.位置 = 0
    _启动窗口.进度条7.位置 = 0
    _启动窗口.进度条8.位置 = 0

    ' 2.让停止按钮为灰色 开启按钮正常
    _启动窗口.按钮_开启.禁止 = 假
    _启动窗口.按钮_关闭.禁止 = 真
    ' 3. 清空编辑框的内容
    _启动窗口.编辑框_日志.内容 = “”


.如果真结束



猜你喜欢

转载自www.cnblogs.com/zjl8455482/p/10452650.html