|
本帖最后由 落款hMZ 于 2017-5-4 18:00 编辑
以前我一直没有测试过多线程大并发下调用ScriptControl组件计算js代码的问题,今天测试了一下,在网上找了一些资料分享给大家,对于有些人来说或许非常重要!!!
易语言计算js,目前大家基本上都是调用ScriptControl这个插件吧,常规的代码如下:
注意这里有个CoInitialize,我曾非常偶然的碰到过一次程序崩溃,当时并没有太在意,今天去查询了一下CoInitialize这个函数
网上给出的解释是,CoInitialize以线程为单位,告诉windows系统要给COM组件分配一个运行空间,并且,由这个函数分配的运行空间是单线程的!!!(经热心网友指正,这句话有错误,应该是:由CoInitialize分配的运行空间是串行的)
也就是说,实际上,CoInitialize这个函数不支持多线程(经热心网友指正,这句话有错误,不是不支持多线程,而是不支持并行调用),于是我做了一个测试,就是附件里的,用1400个线程循环计算某个js,每个线程连续计算1000次,然后,很悲剧的是,电脑直接死机,我想截图一下都没办法,系统直接卡死了,只能按机箱上的重启按钮
后来我减少线程,减少循环次数重新计算,发现问题了,这样多线程大并发下计算结果会有错误,并且程序很容易崩溃!
可怕吗?这个DLL在精易模块中封装成 线程_初始化COM库 ,并被广泛应用,大家以为是个多线程命令,可是实际上他并不支持多线程啊,多线程下会崩溃,计算结果也会出错!!(经热心网友指正,这句话有错误,不是不支持多线程,而是不支持高并发并行调用)
继续找资料,被我发现了 CoInitializeEX 这个函数,他比CoInitialize多了一个dwCoInit 参数,来定义用什么方式分配COM组件的运行空间
方式分为 STA 单线程模式 和 MTA 并发多线程模式
系统里很多COM组件在设计的时候已经决定好了到底是采用STA 还是采用 MTA,所有MTA的COM组件也可以用STA方式分配空间,但是STA的COM组件不能用MTA方式分配空间(另外还有一些组件是BOTH的,代表STA 和 MTA均可)
所以说如果你没有并发要求 用STA是最稳妥的,可以适应任何COM组件,而我们常用的CoInitialize就是以STA方式分配运行空间的
可是如果有并发要求呢,如果大并发下,你只分配一个单线程空间去运行COM组件,所有线程都会访问同一个COM运行空间(不管你在多少个线程里调用了CoInitialize多少次),那么可怕的问题就出现了,大量的读写冲突等等导致计算结果出错,程序出错
那么再看 CoInitializeEX,他是 CoInitialize的上层版本,他的第二个参数允许你定义分配空间的方式,第二个参数取值如下
也就是说,CoInitialize(0) 等效于 CoInitializeEX(0,2)
网上还说:CoInitializeEX的第二个参数除了COINIT_APARTMENTTHREADED 和COINIT_MULTITHREADED标记外,其余的标记可以组合使用。
那么继续测试,把CoInitialize 换成 CoInitializeEX以后,第二个参数设置为0(也就是COINIT_MULTITHREADED),让程序以MTA的方式分配COM运行空间
程序稳定无比,只不过允许速度稍慢,然后把第二个参数换成8( 0和8的组合),速度也确实快了不少
以此类推,winhttp的COM方式也是可以支持MTA的,
很多高并发的winhttp访问崩溃原因可能就是因为 CoInitialize不恰当问题,如果改为CoInitializeEX 估计稳定性可以提升不少(具体没有测试)
附件是高并发计算js的测试程序,大家可以试一下,如有错误,请指正
另外补充一点:测试程序里注释掉了的许可区是我使用CoInitialize 的时候,用许可区一个个计算js,程序还是崩溃了,必须用CoInitializeEX 才不会崩溃
==================================================================================================
多谢20楼 御风软件 的讨论和关注
我这个帖子里所说的一切的一切,都有一个前提,那就是:
这个测试程序 使用CoInitializeEX(0,0) 不会崩溃,可以很顺畅的运行,而如果使用 CoInitializeEX(0,2) 或者 CoInitialize(0),就会出现崩溃的问题
这个才是讨论的重点,而不是单独讨论 STA本身是否是线程安全的
由 19楼黑猫よ__ 指出我的调用可能有问题后,我把CoInitialize(0)放在了循环的外面,重新测试,发现仍然崩溃
按照您帖子中的猜测,我的代码有问题或者易语言本身有问题,那为什么 使用CoInitializeEX(0,0)程序稳定运行呢?我帖子内的代码是大家广泛使用的计算js的方式,易语言我们也改变不了它,那么同样条件下我认为我们可以得出“使用CoInitializeEX(0,0)在高并发中更安全”的结论
另外注意的是,多并发和多线程不是一回事,在多线程里面安全不代表高并发的时候也安全,线程安全跟可以支持高并发没有必然的联系,STA当然是线程安全的,这个我帖子里也说了,但是高并发下是否也安全呢?
最后,您的帖子里有一句话我非常不能赞同:高并发的情况下,别说易语言了,其他语言未处理好也会崩溃!只是会比易语言好点而已
是这样吗?我的理解是,只要是在windows机制允许范围内的高并发,任何崩溃都是有原因的,且可以得到解决的,也是应当得到解决的,32位程序最多支持的线程是1485个左右,只要windows系统没有崩溃,蓝屏黑屏,而程序崩溃了,被强制退出了,那肯定就是代码里有跟windows相冲突的地方,实际上这个地方并不难找到 |
评分
-
查看全部评分
|