图文多线程入门教程
Posted 易语言自习室
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图文多线程入门教程相关的知识,希望对你有一定的参考价值。
易语言写多线程应用要么使用多线程相关的api支持库或模块,其实那些支持库或模块也都是封装的api,但是要比api使用方便。 本次教程以易语言官方的多线程支持库为例。
一、加载多线程支持库
支持库勾选上之后就可以使用易语言的多线程支持库了。
二、多线程创建线程的命令:启动线程
命令名:启动线程
创建并启动一条线程,可重复使用以创建多条线程,成功返回真,失败返回假。
参数 |
数据类型 |
说明 |
参数<1>的名称为“欲执行的子程序” |
子程序指针(SubPtr) |
本参数提供创建线程时欲启动的子程序,根据是否需要传递参数数据,该子程序必须没有或具有一个整数型参数,否则将出错。 |
参数数据 |
整数型(int) |
可以被省略。本参数提供线程被启动时传递到欲启动子程序的整数数据。如果本参数未被省略,此时被启动子程序必须接收一个整数型参数,否则将出错。 |
线程句柄 |
整数型(int) |
,可以被省略,提供参数数据时只能提供变量。如果提供了本参数,将向参数变量写入线程句柄(Windows下为HANDLE,Linux下为pthread_t),请在适当的时机关闭该句柄。如果不提供本参数接收线程句柄,内部将自动处理线程句柄。 |
首先,先演示创建一条线程(控制台程序下):
注意:&子程序1 代表子程序1的子程序指针
执行结果:
这时候子程序1 将不是在主线程中执行的,而是在线程句柄为552的新线程中执行,和主线程互不相关。
接下来,我们通过下面的代码理解下为什么要使用线程:
如果按钮被按下之后,只要循环不结束,界面是不能响应任何消息的,也就是拖动点击什么的都没用,相当于卡死。
但是如果把按钮下调用的子程序1 ,改为启动线程 (&子程序1, , ),则窗口可以正常响应消息,因为创建了一条新的线程来执行子程序1,主线程可以继续处理窗口消息。
三、多线程关闭线程句柄的命令:关闭线程句柄
命令名:关闭线程句柄
返回真表示已成功关闭线程句柄。在Linux下,如果线程已经结束,本命令可能返回假。本命令为初级命令。
参数 |
数据类型 |
说明 |
线程句柄 |
整数型(int) |
可通过“启动线程”的第三个参数获取线程句柄。 |
演示关闭线程句柄的例子:
执行结果:
注意:每次启动线程的句柄都是不确定的
在启动线程之后习惯性地关闭线程句柄释放资源,你可能会问:我创建了线程句柄就不关闭也没见怎么样?就像易语言多线程之启动线程中一样,也没见怎么样,但是这只是创建了一个线程来演示,如果线程持续创建且不释放就会出现内存占用不断增加的情况。此外,关闭线程句柄,顾名思义,是把线程句柄给关闭掉,而不是把线程给关闭掉,这点要分清楚!关闭线程句柄,只是把它的句柄给关闭了,关闭了线程句柄的线程可能继续在执行,但是没了句柄我们已经不能对这条线程进行控制了。
四、多线程等待线程的命令:等待线程
命令名:等待线程
等待,直到指定线程结束或等待超时才返回。返回真表示等待成功。注意,在Linux下暂不支持超时等待。本命令为初级命令。
参数 |
数据类型 |
说明 |
线程句柄 |
整数型(int) |
可通过“启动线程”的第三个参数获取线程句柄。 |
等待时间 |
整数型(int) |
可以被省略。指定等待时间,单位为毫秒。如果为0或负数,或被省略,表示不限定等待时间。 |
我们可以通过等待线程来判断一个线程是否结束:
执行结果:
但是这样还有一个问题,本来用多线程的本意是为了子程序1的循环不影响窗口的消息响应,但是加了一个等待线程又把主线程阻塞了,不符合我们的本意。
解决方法就是把等待线程放到另一个线程中去:
执行结果:
如此,在不阻塞主线程的情况下完成了等待线程。
五、多线程强制结束线程的命令:强制结束线程
命令名:强制结束线程
返回真表示执行成功。本命令为初级命令。
参数 |
数据类型 |
说明 |
线程句柄 |
整数型(int) |
可通过“启动线程”的第三个参数获取线程句柄。 |
强制结束一个线程的例子:
执行结果:
点击强制结束线程按钮后,
判断线程是否正在等待,如果是正在运行,那么,执行制结束线程,制结束线程是不管线程有没有结束,都强制结束线程;如果已经结束,则关闭线程句柄。
强制结束线程和等待线程比起来,更为霸道,可以说是蛮不讲理,也容易处理不当造成程序错误,所以,不推荐使用。
六、多线程防止线程冲突的命令:多线程许可证
我们在使用多线程时会出现资源独享的情况,这时候,我们使用加入许可区之后可以防止多个线程同时访问公用变量是发生冲突。加入许可区的代码同时只允许一个线程访问以避免冲突。
主要命令包括:
创建许可区:
创建并返回一个进入许可证数值,此许可证值用作进入程序中的指定许可代码区,以避免多线程冲突。成功返回非零整数值,失败返回0。所创建的许可证在不再使用后,必须使用“删除进入许可证”命令将其删除。本命令为初级命令。
删除进入许可证:
删除由“创建进入许可证”命令所创建返回的进入许可证。成功返回真,失败返回假。本命令为初级命令。
参数 |
数据类型 |
说明 |
进入许可证 |
“整数型(int) |
本参数应提供由“创建进入许可证”命令所创建并返回的数值。 |
进入许可区:
根据已经创建的许可证进入指定许可代码区,在此线程未退出之前,其它线程如要通过同一个进入许可证进入该许可代码区则必须先等待此线程退出许可代码区,从而保证了指定许可代码区在任何时候都只能有一条线程进入并执行。本命令为初级命令。
参数 |
数据类型 |
说明 |
进入许可证 |
整数型(int) |
本参数应提供由“创建进入许可证”命令所创建并返回的数值。 |
退出许可区:
指示当前线程将退出许可代码区,并允许其它使用同一进入许可证的线程进入此许可代码区。本命令为初级命令。
参数 |
数据类型 |
说明 |
进入许可证 |
整数型(int) |
本参数应提供由“创建进入许可证”命令所创建并返回的数值。 |
反例:不加许可证
调试输出结果:
* 8
* 9
* 7
* 6
* 5
* 4
* 3
* 2
* 1
在执行一次:
* 8
* 7
* 9
* 6
* 5
* 4
* 3
* 2
* 1
* 0
我们可以明显的发现问题,,虽然最终是把num减到了0,但是结果完全是乱的。
利用许可证解决上面的问题:
输出结果:
* 9
* 8
* 7
* 6
* 5
* 4
* 3
* 2
* 1
* 0
用了许可证之后每次都是这样的稳定结果。
七、多线程例程
接下来,我们把上述命令组合在一起搭配使用,组成一个简单的多线程例程
注意几点:
1.多线程不是越多线程越好,控制在30左右的线程个数是一个比较合理的区间;
2.从实战经验上来看,要做好对句柄的处理;
3.多线程的崩溃的问题,不要只盯着框架本身,而多考虑是执行的代码问题,就好像执行下图的代码,一万个都不会出现问题,而执行实际的代码,则弄不好就会报错。
(易语言自习室对部分内容进行修改完善)
以上是关于图文多线程入门教程的主要内容,如果未能解决你的问题,请参考以下文章