易语⾔多线程的认识与注意事项-(浅谈多线程奔溃)
易语⾔多线程的认识与注意事项- (浅谈多线程奔溃)
什么是多线程:
每个正在系统上运⾏的程序都是⼀个进程。每个进程包含⼀到多个线程。进程也可能是整个程序或者是部分程序的动态执⾏。线程是⼀组指令的集合,或者是程序的特殊段,它可以在程序⾥独⽴执⾏。也可以把它理解为代码运⾏的上下⽂。所以线程基本上是轻量级的进程,它负责在单个程序⾥执⾏多任务。通常由操作系统负责多个线程的调度和执⾏。线程是程序中⼀个单⼀的顺序控制流程.在单个程序中同时运⾏多个线程完成不同的⼯作,称为多线程.
线程和进程的区别在于,⼦进程和⽗进程有不同的代码和数据空间,⽽多个线程则共享数据空间,每个线程有⾃⼰的执⾏堆栈和程序计数器为其执⾏上下⽂.多线程主要是为了节约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库() 某些学员别被这种坑钱不负责任的⼈骗到]
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论