设为首页收藏本站积分充值 不再解释,用心做事!    

易辅客栈

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手游专用模拟器快速领取论坛金钱免费获取易辅VIP会员
论坛资源失效举报链接
查看: 12073|回复: 6

易语言多线程的认识与注意事项 - (浅谈多线程奔溃)

[复制链接]

签到天数: 387 天

连续签到: 1 天

[LV.9]以坛为家II

186

主题

595

帖子

9092

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
9092

社区QQ达人

发表于 2016-9-15 14:12:24 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转脚本编程。

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

x
本文档酝酿了一段时间了,吸取了一些前辈的经验以及平时积累一些简单的理解,内容有点长,纯手动编辑发布,某些特殊的知识我们无法制作成视频,仅以制作成文档形式,希望能让您有所收获。[参照以前一些老师的部份观点:点击查看]

什么是多线程:

            每个正在系统上运行的程序都是一个进程。每个进程包含一到多个线程。进程也可能是整个程序或者是部分程序的动态执行。线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行。也可以把它理解为代码运行的上下文。本帖子由<易辅客栈>编辑发布。所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务。通常由操作系统负责多个线程的调度和执行。
           线程是程序中一个单一的顺序控制流程.在单个程序中同时运行多个线程完成不同的工作,称为多线程.
          线程和进程的区别在于,子进程和父进程有不同的代码和数据空间,而多个线程则共享数据空间,每个线程有自己的执行堆栈和程序计数器为其执行上下文.多线程主要是为了节约CPU时间,发挥利用,根据具体情况而定. 线程的运行中需要使用计算机的内存资源和CPU。

一.关于多线程基本认识:
1、关闭线程句柄对线程的运行不会有影响,关闭句柄并不代表结束线程;
2、线程句柄是用于对线程挂起、恢复、结束等操作,线程创建后,都会有一个线程句柄,如果不需要对线程句柄进行操作,建议立即关闭线程句柄;
3、线程句柄必须在适当的时候关闭,否则会造成句柄泄露,但不同于内存泄露。该泄露无前兆特征,并且极大可能造成程序崩溃
二.注意事项:
1、虽然启动线程要比启动进程要快,但是启动线程仍是比较耗时的,因此,不要频繁的启动、退出线程,而是启动线程后将各种任务处理完成后才退出(这种和线程池差不多);
2、对窗口各种组件操作,最好是在创建该窗口的线程上进行操作,如果在其它线程上操作,可能会引起程序出错等情况(该错误是随机出现的)。(未找到直接又安全的调用其他线程创建的组件的方法,有知道的人,麻烦告诉一下,谢谢!)
3、线程运行次序并不是按照我们创建他们时的顺序来运行的,CPU处理线程的顺序也是不确定的。
4、读/写共享资源时一般需要使用许可区,当然,在明知读/写共享资源不会出现错误时,就不需要许可区,这样可提高性能。
5、在编写多线程时,必须以多线程的方式考虑读/写共享资源,以避免出错,不然的话,可能会出现各种问题,如:意外退出、同时多核CPU中由于处理线程的。

6、线程中如果需要使用COM对象时,要需将COM对象初始化,比如大漠插件,填表等都基于COM对象
7、结束线程时,应该使用正常的控制代码使线程退出,强烈反对使用强制结束线程(),该命令极可能造成一些资源未释放,从而导致程序的不稳定。基于线程的生命周期,线程代码最好能让其线程代码自动执行完毕自动退出线程,这样是最稳妥的处理方式.
8、线程不能频繁的发消息给窗口,频繁的发消息给窗口,可能会造成窗口响应其他事件的缓慢,也是就让人感觉程序运行很慢;

三.多线程的误区:
1、使用处理事件()。非窗口的线程是没有窗口消息循环,而处理事件()命令是用于消息循环,因此在非窗口的线程上是不必加入“处理事件()”命令;
2、线程越多越好。线程并非越多越好,有些人将单线程改成多线程后,发现程序能处理更多的任务了,实际上这种方法是建立别的程序的痛苦之上(当然系统有空闲资源就并当别论了),别的程序可能因此而变慢。并且,线程数过多,会使CPU在线程间切换的开销增加,因而使速度变慢.
3、多线程下频繁操作线程,如强制关闭,挂起线程,等待线程等,在频繁操作下有线程的阻塞有可能造成程序不稳定或者奔溃,在易语言当中线程是极其脆弱的.并且当线程处于高速的循环代码中强制结束线程极大可能会造成程序不稳定或者直接内存溢出奔溃或者某些资源无法释放,当有资源无法释放程序的流畅性以及稳定性将大打折扣.
4、多线程对于全局变量/程序集变量等公共变量的操作中,一个赋值,其他只读取是不会有问题的,这个问题是否定的,在某些变量类型中会出现"踩空"的现象,导致内存访问错误.此类编写方式一般建议将功用变量声明为整数型.

四、许可区
1、许可区(一般称为临界区),不论是硬件许可资源,还是软件许可资源,多个线程必须互斥地对它进行访问,每个线程中访问许可资源的那段代码称为许可区。
2、注意事项:
①、如果有若干线程要求进入许可区,一次仅允许一个线程进入;
②、任何时候,处于许可区内的线程不可多于一个。如已有线程进入自己的许可区,则其它所有试图进入许可区的线程将被挂起,并一直持续到进入许可区的线程退出;
③、进入一个空闲的许可区时,耗时极少,但是进入一个需等待的许可区时,耗时相对较长,因此需要避免经常出现进入需等待的许可区;
④、创建后许可区,在不再使用时,需要将其删除;
⑤、在使用许可区时,应尽量减少许可区内代码,避免使用需长时间处理的代码,使进入许可区的线程能尽快退出,以便其它线程能进入许可区;
⑥、避免将整个线程处于许可区内,尽管它不会出错,但是由于后来要求进入许可区的线程全部会被挂起,也就会出现虽然是多线程,但实际是以单线程方式执行;
⑦、访问相同的许可资源时,必须是以相同的许可区进入访问,以不同的许可区进入访问将可能会使许可区变的无意义(我在这个坑里蹲了很久,郁闷啊!)。
3、许可区缺点
①、无法侦测某个许可区是否可进入,如果非要进行记录,一般建议使用整数型变量进行赋值记录,但是太方式会增大程序资源用.
4.线程同步
许可区在线程间进行同步是运用得最多的,这种速度最快,但只能用于本进程的线程同步;
5.线程通信
线程通信是一般都是需要配合线程同步来使用:
1、使用全局变量进行通信,推荐使用这种方法,目前是最快、最方便的通信方式;
2、使用消息通信(需要有消息队列才能使用);3、基于许可区的变量通讯,也就是我们之前的类似线程同步方式;

五、易语言多线程的注意点:
1).各种内存错误
线程a对变量操作的时候b也操作,a改写了文本申请了新的内存地址同时修改了指针然后释放了原指针,但是b读取了原指针需要读取数据的时候,a已经把指针释放了.然后就各种内存错误。。
值得注意的是,一边读一边执行写操作也不行,
你线程a对全局文本变量赋值"1234567",那么在线程b对全局变量读写前,会经过至少两个步骤
1、获取内存区域大小,假设是8的话
2、读取内容 而实际上进行到读取第8位的时候,你线程a重新给全局文本变量赋值“123456”,这就导致“踏空”,于是程序直接崩溃。而对于长度固定的变量进行读写时,就算读取到的数据是错误的,也不至于崩溃,比如固定位数的整数型变量.
2).关于易语言控件操作问题。。
控件操作一定要加许可证。。这个大家都知道。。
但这样依然不会很稳定。。一般建议不要频繁对控件过多的进行操作,比如易语言的超级列表框.
3).易语言启动线程,结束线程问题
1.启动我建议用官方的多线程支持库。。或者使用易辅客栈的 线程_启动() 命令
2.结束线程我强烈反对强制结束线程,无论是什么支持库,什么多线程模块,基本都是调用TerminateThread,应该尽量避免这样结束线程,能自动退出线程是最好不过的了.
3.有些人喜欢在程序执行的过程中喜欢退出线程或者也叫终止线程,该函数基本都是调用ExitThread来将线程终止的,该函数将终止线程的运行,并导致操作系统清除该线程使用的所有操作系统资源。但是有一些资源将不被撤消。这也有可能造成程序的不稳定,时间久了有可能会导致程序自动关闭/奔溃等.
4.关于句柄问题,不需要一定要CloseHandle,防止句柄泄露,一般如果不需要对该线程进行操作的,创建线程都不提供句柄参数,让系统自动销毁,或者在操作完第一时间关闭句柄
4).
易语言常见的线程奇葩问题

某些易自身问题,因为这很大程度是易本身的问题,并且无法处理,我们只能选择尽量避免.多数已在新版本易中修复
(1).易语言本身的命令问题
易语言本身的分割文本命令、读写配置项()命令、
这些命令在多线程中会出问题在易语言业界中已经不是秘密了!

很多人喜欢在线程中不断地保存或者读取配置信息,这个做法是不可取的,随时有可能再某个时间奔溃或者在较长一段时间后出现错误.
在必要断读取的条件下,可以尝试文本文件的方式,只能说比读写配置会好点,具体稳定性请自行测试.
(2).易语言本身的延时,延迟
在线程中如果非要使用,尽量选择延时命令,也可与在延时后加处理事件,尽量避免用 延迟,请使用[易辅客栈模块]中的辅助延时()命令

六、大漠多线程:
1.1个线程必须拥有一个大漠对象,
2.每个线程对象在操作使用完毕后必须销毁对象
3.部分窗口在使用大漠 UnBindWindow 函数进行解绑时,可能会有残留也就是无法完全解绑.在此情况下,重复绑定可能会造成程序或者窗口奔溃,解决办法是使用 ForceUnBindWindow 进行强制解绑.
4.很多人在使用大漠线程时,喜欢初始化COM对象,正确的使用方法是,在程序开始是进行初始化以及在程序结束时取消初始化.并不是一个程序就使用一次.像一些奇葩模块,光这个命令都有几个名称[如取消_COM库,取消_线程COM库,我就不一一的举明了,像易辅客栈的,只有一个 那就是 初始化COM库() 卸载COM库()  某些学员别被这种坑钱不负责任的人骗到]

易辅学院--欢迎你,有你更出众。 易辅做最真最好的服务 www.yifuxueyuan.com

该用户从未签到

0

主题

4

帖子

18

积分

新手上路

Rank: 1

积分
18
发表于 2017-8-6 09:57:42 | 显示全部楼层
支持楼主,支持易辅客栈,以后经常来
易辅学院--欢迎你,有你更出众。 易辅做最真最好的服务 www.yifuxueyuan.com

签到天数: 2 天

连续签到: 1 天

[LV.1]初来乍到

1

主题

14

帖子

45

积分

新手上路

Rank: 1

积分
45
发表于 2017-11-24 09:15:39 | 显示全部楼层
楼主超给力,易辅客栈真是难得给力的平台啊。
易辅学院--欢迎你,有你更出众。 易辅做最真最好的服务 www.yifuxueyuan.com

签到天数: 2 天

连续签到: 1 天

[LV.1]初来乍到

1

主题

14

帖子

45

积分

新手上路

Rank: 1

积分
45
发表于 2017-11-24 09:17:36 | 显示全部楼层
好UIu 
易辅学院--欢迎你,有你更出众。 易辅做最真最好的服务 www.yifuxueyuan.com

该用户从未签到

0

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15

社区QQ达人

发表于 2018-2-2 01:39:26 | 显示全部楼层
少时诵诗书所所所所所所所所所所
易辅学院--欢迎你,有你更出众。 易辅做最真最好的服务 www.yifuxueyuan.com

该用户从未签到

0

主题

2

帖子

7

积分

新手上路

Rank: 1

积分
7

社区QQ达人

发表于 2018-7-1 08:02:26 | 显示全部楼层
支持楼主,支持易辅客栈,以后经常来
易辅学院--欢迎你,有你更出众。 易辅做最真最好的服务 www.yifuxueyuan.com

该用户从未签到

0

主题

2

帖子

7

积分

新手上路

Rank: 1

积分
7

社区QQ达人

发表于 2018-7-1 09:19:34 | 显示全部楼层
楼主超给力,易辅客栈真是难得给力的平台啊。
易辅学院--欢迎你,有你更出众。 易辅做最真最好的服务 www.yifuxueyuan.com
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

易辅解答服务
 
 
VIP咨询
VIP办理
易辅交流4群:
【易辅客栈】脚本4群
易辅交流5群:
【易辅客栈】交流5群
易辅交流6群:
【易辅客栈】交流6群
工作时间:
10:00-22:00

QQ|小黑屋|手机版|Archiver|VIP介绍|积分充值|易辅客栈 ( 苏ICP备16034616号-1 )

GMT+8, 2024-4-29 11:18 , Processed in 0.359642 second(s), 73 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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