无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
楼主: mdyblog
打印 上一主题 下一主题

[更新376#2825]PECMD2012.1.80.13_Win32_64.多窗口多线程.裸机系统2.3.3.1+18M酷M...

    [复制链接]
5431#
发表于 2013-4-13 00:19:50 | 只看该作者
mdyblog 发表于 2013-4-13 00:12
>>应该可以确定不是重复写了主线的变量,因为那个变量是用来保存 ud 区的硬盘号的,在一个进程中只会初始 ...

就是无法确定重现条件,每次重启有时正常,有些时候又不行,就算出错也不一定是加载同一个文件的时候出错,所以很让人抓狂。而且这问题发生的频率也不高,重启又花时间,基本可以归为疑难杂症了,等时间充裕的时候来慢慢试。
回复

使用道具 举报

5432#
发表于 2013-4-13 00:43:13 | 只看该作者
clonecd 发表于 2013-4-13 00:28
以前我跑多线程也调试了很久,后来我干脆改成两条线程了,3、4条线程很让人抓狂的。

就是啊,要不是 pe 启动用多线能明显快很多(单核单线老机能接近10秒,总启动过程1分钟左右,赛扬440M 1G内存的机器),实在很有吸引力的话,还是稳定压倒一切的。
回复

使用道具 举报

5433#
 楼主| 发表于 2013-4-13 08:10:33 | 只看该作者
本帖最后由 mdyblog 于 2013-4-13 09:34 编辑
2010qaqz111 发表于 2013-4-13 00:43
就是啊,要不是 pe 启动用多线能明显快很多(单核单线老机能接近10秒,总启动过程1分钟左右,赛扬440M 1G ...


可以用排除法。
先不用多线程。
THREAD* 改为CALL 。
没事,就用其中一半 作为 一个线程。
直到 最终为正常的多线程。
这样2分法, 没几次就能定位到问题代码。

还有少用 CALL $ , 免得 干扰。
CALL $则另开一个PECMD:
EXEC  =%MyName%  CALL $....

2个线程应该没问题, 我还以为几百个啦。 我试个上百个的, 没问题。

THREAD* 。。。。
最好这样写:
THREAD*$  ...
这样 变量都会换成其值。 参见 PECMD补充说明.doc
回复

使用道具 举报

5434#
发表于 2013-4-13 08:21:19 | 只看该作者
本帖最后由 2010qaqz111 于 2013-4-13 09:35 编辑
mdyblog 发表于 2013-4-13 08:10
可以用排除法。
先不用多线程。
THREAD* 改为CALL 。


CALL $?是注册 dll 的?基本没用这个来着,调用 dll 函数的用法也没有,只有一个地方注册 Open++ 的 dll 用了下,还是在外置程序里面,跟启动的几个关键过程没关系。

改成 CALL 找问题,可问题是用 THREAD* 的时候出问题就只是 10 次大概碰到 1 次左右,改成 CALL 的话就更不容易遇到了,囧
回复

使用道具 举报

5435#
发表于 2013-4-13 09:28:35 | 只看该作者
本帖最后由 2010qaqz111 于 2013-4-13 09:34 编辑

刚刚遇到这样的情况:

1008        12788798187        [GETF# 0,0xb037S#547,&&FTAR]        <1>        :函数不正确。
1008        12788994655        [ENVI-ret &MBIN=0xFFFFFFFF]        <0>        :操作成功完成。
1008        12789116836        [ENVI-ret &BLEN=547]        <0>        :操作成功完成。

1008        12789988236        [ENTER:**mem]               
1008        12796277173        [0xFFFFFFFF]        <2>        :系统找不到指定的文件。
1008        12796446272        [LEAVE:**mem]               
1008        12802225466        [LOAD **mem &MBIN ]        <0>        :操作成功完成。

GETF# 出错了,然后 LOAD **mem 直接退出了。
GETF# 在什么情况下会出错然后在变量里返回 -1?


这些代码是在新线程中运行的,新线程一开始的部分读一个在主线程设置的PE变量失败返回了空,后面读文件遇到了这个错误。
回复

使用道具 举报

5436#
 楼主| 发表于 2013-4-13 09:41:06 | 只看该作者
本帖最后由 mdyblog 于 2013-4-13 09:45 编辑
2010qaqz111 发表于 2013-4-13 09:28
刚刚遇到这样的情况:

1008        12788798187        [GETF# 0,0xb037S#547,&&FTAR]                :函数不正确。


>>1008        12788798187        [GETF# 0,0xb037S#547,&&FTAR]        <1>        :函数不正确。
GETF# 第一个参数不对。
是不是应该为 \\.\PhysicalDrive0

你怎么还在用旧版 PECMD ??!!  改了半天, 你没用啊?
回复

使用道具 举报

5437#
发表于 2013-4-13 10:01:21 | 只看该作者
最新版的啊,410-02的
回复

使用道具 举报

5438#
发表于 2013-4-13 10:03:01 | 只看该作者
mdyblog 发表于 2013-4-13 09:41
>>1008        12788798187        [GETF# 0,0xb037S#547,&&FTAR]                :函数不正确。
GETF ...

第一个参数也应该是从主线程读来的,怎么只剩一个0了,我再查查。
回复

使用道具 举报

5439#
发表于 2013-4-13 10:24:58 | 只看该作者
本帖最后由 2010qaqz111 于 2013-4-13 10:26 编辑

1008        12721022534        [EXEC* &UDINFO=!FBINST --list]        <0>        :操作成功完成。
1008        12721208739        [RSTR &P=1,(hd0): 625142448 (298g) *]        <0>        :操作成功完成。
1008        12721391522        [LPOS &P=:,,(hd0): 625142448 (298g) *]        <0>        :操作成功完成。
1008        12723667034        [CALC #&P=6-1]        <0>        :操作成功完成。
1008        12724539900        [LSTR &UDHD=5,(hd0)]        <0>        :操作成功完成。
1008        12782479927        [EXEC* &&FBINFO=!FBINST (hd0) info]        <0>        :操作成功完成。
1008        12785635147        [LPOS*** &P="PE/SCRIPTS/DRV.WCS",,version: 1.6               
1008        12786081354        [SED &UDHDW=0,[^0-9],,(hd0)]        <0>        :操作成功完成。<-- 这一行是把 (hd0) 取出其中的 0
1008        12786177145        [SET UDHDW=\\.\PhysicalDrive0]        <0>        :操作成功完成。 <-- 这一行是设置读取目标的,在 0 前面加上 \\.\PhysicalDrive
1008        12786392673        [SET UDINFO=version: 1.6               
1008        12786500193        [IFEX $0!=182,]        <0>        :操作成功完成。
1008        12786541246        [FIND $*=*,]        <0>        :操作成功完成。
1008        12786578390        [FORX *NL &UDINFO,&UDHD,]        <0>        :操作成功完成。
1008        12786653165        [FIND $\\.\PhysicalDrive0=,]        <0>        :操作成功完成。
1008        12786722564        [ENVI-ret &P=182]        <0>        :操作成功完成。
1008        12786765083        [UDFIND "PE/SCRIPTS/DRV.WCS" &P]        <0>        :操作成功完成。
1008        12786858430        [IFEX $0=182,TEAM {ENVI-ret3 &BLEN=-1|EXIT _SUB}]        <0>        :操作成功完成。
1008        12786898994        [FIND $=,]        <0>        :操作成功完成。
1008        12787124297        [IFEX $182=-1,LPOS*** &&P="PE/SCRIPTS/DRV.WCS",,version: 1.6               
1008        12787259186        [IFEX $0=182,TEAM {ENVI-ret2 &BLEN=-1|EXIT _SUB}]        <0>        :操作成功完成。
1008        12787394075        [CALC #&&SECT=1+182]        <0>        :操作成功完成。
1008        12787472760        [CALC #&&FLEN=2+182]        <0>        :操作成功完成。
1008        12787854455        [MSTR &SECT=<183>version: 1.6               
1008        12788193143        [MSTR &FLEN=<184>version: 1.6               
1008        12788798187        [GETF# 0,0xb037S#547,&&FTAR]        <1>        :函数不正确。

最后一行的代码是 GETF# %&UDHDW%,%&SECT%S#%&FLEN%,&&FTAR,到这里 UDHDW 就只剩个 0 了,原因不明。

                SED &UDHDW=0,[^0-9],,%&UDHD%
                SET UDHDW=\\.\PhysicalDrive%&UDHDW%

前面的这2行是在同一个层级中,UDHDW 是文件级定义的 PE 变量。

这没头没尾的也不知道看得明白不。
回复

使用道具 举报

5440#
 楼主| 发表于 2013-4-13 10:26:37 | 只看该作者
2010qaqz111 发表于 2013-4-13 10:01
最新版的啊,410-02的

>>>>1008        12788798187
不是, 已经很老了。
新的版本时间都有3为小数。如:
》》》7956        8333347438515.263        [THREAD*$ TEST1 192.168.1.109   109]
回复

使用道具 举报

5441#
发表于 2013-4-13 10:28:52 | 只看该作者
本帖最后由 2010qaqz111 于 2013-4-13 10:37 编辑
mdyblog 发表于 2013-4-13 10:26
>>>>1008        12788798187
不是, 已经很老了。
新的版本时间都有3为小数。如:


哦,这个是从 excel 里copy出来的,excel 导入的时候把小数点干掉了。


984        12788307504.937        [SED &UDHDW=0,[^0-9],,(hd0)]        <0>        :操作成功完成。
984        12788395475.758        [SET UDHDW=\\.\PhysicalDrive0]        <0>        :操作成功完成。
1008        12788798186.628        [GETF# 0,0xb037S#547,&&FTAR]        <1>        :函数不正确。
984        12788845593.126        [SET UDINFO=version: 1.6

文本文件里那一行是这样的,excel 把小数部分收上去了。



┃    │格式│LOGS [**RAW=0/1] [**ON=0/1] [[*文件路径][,数值]]                                            ┃

**RAW 是执行前输出还是执行后?
回复

使用道具 举报

5442#
 楼主| 发表于 2013-4-13 10:34:56 | 只看该作者
本帖最后由 mdyblog 于 2013-4-13 10:36 编辑
2010qaqz111 发表于 2013-4-13 10:28
哦,这个是从 excel 里copy出来的,excel 导入的时候把小数点干掉了。


(同一个进程)多线程个数限制

32位不要超过100 个
64位最好不超过3500 个


下面是测试结果
多线程个数:
Win7X64---Win32程序: 108
   7956        8333347438515.263        [THREAD*$ TEST1 192.168.1.109   109]        <8>        :存储空间不足,无法处理此命令。

XP32: 117
   2880        2153003061025.792        [THREAD*$ TEST1 192.168.1.118   118]        <8>        :存储空间不足,无法处理此命令

Win7X64-Win64程序: >3500
回复

使用道具 举报

5443#
发表于 2013-4-13 10:39:06 | 只看该作者
本帖最后由 2010qaqz111 于 2013-4-13 10:40 编辑

没有那么多线程的,只有3个,LOG里也只有3个线程号,搜索LOG没有找到<8>。
回复

使用道具 举报

5444#
 楼主| 发表于 2013-4-13 10:40:44 | 只看该作者
本帖最后由 mdyblog 于 2013-4-13 10:43 编辑
2010qaqz111 发表于 2013-4-13 10:28
哦,这个是从 excel 里copy出来的,excel 导入的时候把小数点干掉了。


**RAW   还是执行后输出。
**RAW 就是不解释, 原样输出

ABC为123
MESS %ABC%
**RAW 则LOGS   [MESS %ABC%]
    否则LOGS   [MESS 123]
回复

使用道具 举报

5445#
 楼主| 发表于 2013-4-13 10:42:23 | 只看该作者
2010qaqz111 发表于 2013-4-13 10:39
没有那么多线程的,只有3个,LOG里也只有3个线程号,搜索LOG没有找到。


这是通告,以免有人开多了。 不是说你这个。 我知道你就开2个线程。
回复

使用道具 举报

5446#
 楼主| 发表于 2013-4-13 11:02:17 | 只看该作者
2010qaqz111 发表于 2013-4-13 10:24
1008        12721022534        [EXEC* &UDINFO=!FBINST --list]                :操作成功完成。
1008        12721208739        [RSTR &P=1,(hd0): ...

UDHDW 可以建一个 线程的私有拷贝
{
         SET-def     UDHDW=%&UDHDW%   //建立一个同名本级临时变量, 自动转为 线程私有变量, 屏蔽上级的变量。
         THREAD*$    .....  
}
这样  线程中的 UDHDW 就是私有的, 主线程和其他线程 不能修改。


如果不需要直接回传数据, 可以 直接 THREAD$  ...
不带*, 这样 所有P非全局PE变量(不带::的变量) 都自动转为 线程私有变量。
     此时还可以同个 ENVI    @@SENDMSG 来回传数据/线程同步。
回复

使用道具 举报

5447#
 楼主| 发表于 2013-4-13 11:37:00 | 只看该作者
2010qaqz111 发表于 2013-4-13 10:28
哦,这个是从 excel 里copy出来的,excel 导入的时候把小数点干掉了。

给你加了2个LOGS开关

**p[-]
**2[-]
**p为执行前打印;**2为前后都打印,后缀-为取消
回复

使用道具 举报

5448#
发表于 2013-4-13 11:39:06 | 只看该作者
SET &UDHDW
这样的写法如果是在新线程中执行是产生一个线程私有的变量覆盖主线同名吗?线程用 THREAD* 启动的。
回复

使用道具 举报

5449#
发表于 2013-4-13 11:40:16 | 只看该作者
本帖最后由 2010qaqz111 于 2013-4-13 12:12 编辑
mdyblog 发表于 2013-4-13 11:37
给你加了2个LOGS开关

**p[-]


谢谢,我试试看。出问题的地方好像有点眉目了。


**p 和 **2 对 EXEC --logs 开关有效吗?
回复

使用道具 举报

5450#
发表于 2013-4-13 12:03:46 | 只看该作者
THREAD 的几个开关 &*+$ 除了+很好理解其他3个一直都没大弄明白区别,补充说明里的例子也没大看懂。

SET &A=1

这之后的 THREAD LOAD 和 THREAD CALL 是如何对待 A 的?
我一直以为 THREAD* LOAD 或者 CALL 和直接的 LOAD 和 CALL 没有区别。


前面的问题好像是因为主线中一个 THREAD* LOAD 的配置文件中的一句 SET &UDHDW 造成的,不知道是新建了一个线程私有的 UDHDW 还是清空了主线程的,然后这个子线程再次 THREAD* LOAD 一个配置文件,之后子线程和孙子线程里取 UDHDW 就都是空值了。

应该就是这个地方出的问题,我再加一些代码仔细检查一下。
回复

使用道具 举报

5451#
 楼主| 发表于 2013-4-13 12:18:33 | 只看该作者
本帖最后由 mdyblog 于 2013-4-13 12:22 编辑
2010qaqz111 发表于 2013-4-13 11:39
SET &UDHDW
这样的写法如果是在新线程中执行是产生一个线程私有的变量覆盖主线同名吗?线程用 THREAD* 启动 ...


对自线程了来说, 会屏蔽的。不是覆盖。 是新建一个线程私有的UDHDW。 两个变量都在,各是各。
但只能访问子线程的。 由于同名,父线程的那个同名变量子线程访问不了。

但父线程 访问的还是父线程的那个变量。 压根访问不了子线程的变量。
回复

使用道具 举报

5452#
 楼主| 发表于 2013-4-13 12:24:45 | 只看该作者
2010qaqz111 发表于 2013-4-13 12:03
THREAD 的几个开关 &*+$ 除了+很好理解其他3个一直都没大弄明白区别,补充说明里的例子也没大看懂。

SET ...

》前面的问题好像是因为主线中一个 THREAD* LOAD 的配置文件中的一句 SET &UDHDW 造成的,不知道是新建了一个线程私有的 UDHDW 还是清空了主线程的,然后这个子线程再次 THREAD* LOAD 一个配置文件,之后子线程和孙子线程里取 UDHDW 就都是空值了。
是 新建了一个线程私有的 UDHDW,还是空的。
回复

使用道具 举报

5453#
 楼主| 发表于 2013-4-13 12:36:45 | 只看该作者
2010qaqz111 发表于 2013-4-13 12:03
THREAD 的几个开关 &*+$ 除了+很好理解其他3个一直都没大弄明白区别,补充说明里的例子也没大看懂。

SET ...

SET &A=1
这之后的 THREAD LOAD 和 THREAD CALL 是如何对待 A 的?
我一直以为 THREAD* LOAD 或者 CALL 和直接的 LOAD 和 CALL 没有区别。
1: 这之后的 THREAD LOAD 和 THREAD CALL 是如何对待 A 的?

子线程会建立一个自己私有的 拷贝A。 和原来的A各是各。
只有::的全局变量才是共享的。

LOAD  和CALL , 在此问题上一样。

SET &A=1 //拷贝
THREAD     。。。。。。


2: THREAD* LOAD 和 THREAD* CALL 等 THREAD*

就分情况。

1) 如果此时在一个临时执行栈(普通函数,块), 和不带*一样, 会建立拷贝。


     SET &A=1    //拷贝
    THREAD*   。。。。。。


_SUB ABC
     SET &A=1 //拷贝
    THREAD* 。。。。。。
_END

2) 如果此时在一个持久执行栈(窗口_SUB本级, 持久函数), 不会建立拷贝。 直接共享。
如:
_SUB ABC,W100H100   //窗口
      SET &A=1   //共享
     THREAD* 。。。。。。
_END

_SUB ABC, *    //持久函数
     SET &A=1    //共享
     THREAD* 。。。。。。
_END

注意如果外面加一对{},就属于1)了:

_SUB ABC,W100H100 //窗口

      SET &A=1   //拷贝
     THREAD* 。。。。。。
  }
_END
回复

使用道具 举报

5454#
发表于 2013-4-13 12:37:29 | 只看该作者
改成 SET &UDHDW=%&UDHDW% 后查日志看来是正常了,应该就是在子线中的 SET &UDHDW 新建了一个私有变量导致后面读到空变量的。

前面 GETF 读到 0 的原因也清楚了,也是因为这个写法出的问题。

回复

使用道具 举报

5455#
 楼主| 发表于 2013-4-13 12:40:14 | 只看该作者
2010qaqz111 发表于 2013-4-13 11:39
SET &UDHDW
这样的写法如果是在新线程中执行是产生一个线程私有的变量覆盖主线同名吗?线程用 THREAD* 启动 ...


》》SET &UDHDW
》》这样的写法如果是在新线程中执行是产生一个线程私有的变量覆盖主线同名吗?线程用 THREAD* 启动的。
是产生一个线程私有的变量, 屏蔽 主线同名变量。 都在,各是各。
子线程只能访问这个私有的 UDHDW; 访问不了 主线的UDHDW。
回复

使用道具 举报

5456#
发表于 2013-4-13 12:57:52 | 只看该作者
本帖最后由 2010qaqz111 于 2013-4-13 12:59 编辑

LOGS **2 貌似不能放在 {} 里?
  1. IFEX %Desktop%\,
  2. {   LOGS **2 *%Desktop%\z.log
  3. }

  4. SET &A=1
  5. CALC #&A=1+%&A%
复制代码
这样写输出的 LOG 还是只有执行后,命令用 [] 包围的。

日志是否输出是用存放日志的文件夹是否存在作为条件控制的,所以这样写。
{} 里还有其他命令,是设置日志路径变量的,给后面的 EXEC --logs 用。
回复

使用道具 举报

5457#
发表于 2013-4-13 13:06:51 | 只看该作者
本帖最后由 2010qaqz111 于 2013-4-13 13:11 编辑
mdyblog 发表于 2013-4-13 12:36
SET &A=1
这之后的 THREAD LOAD 和 THREAD CALL 是如何对待 A 的?
我一直以为 THREAD* LOAD 或者 CALL ...


_SUB F,* 定义的持久函数是个什么概念?是说这个函数内用 SET& 定义的变量在 _END 后不会销毁,下次进入该函数其值仍然在,就相当于 c 函数里用 static 定义的变量?


THREAD* 与不加 * 的不同之处在于从窗口的_SUB和,*的_SUB里启动子线程的时候,子线程能否共享上级的变量,是这样吗?


那 & 和 $ 又是什么用处?
回复

使用道具 举报

5458#
 楼主| 发表于 2013-4-13 13:49:38 | 只看该作者
本帖最后由 mdyblog 于 2013-4-13 14:19 编辑
2010qaqz111 发表于 2013-4-13 12:57
LOGS **2 貌似不能放在 {} 里?这样写输出的 LOG 还是只有执行后,命令用 [] 包围的。

日志是否输出是用 ...


**2
**RAW
**P
这些开关 都是局部开关, 这样各个线程(函数,块)可以有不同的状态设置。
能够继承。
可以在{}后面或前面
单独加一个
LOGS  **2
  
回复

使用道具 举报

5459#
发表于 2013-4-13 13:57:44 | 只看该作者
mdyblog 发表于 2013-4-13 13:49
**2
**RAW
**P

明白了,我把代码改一下,把这个开关放到顶级去。
回复

使用道具 举报

5460#
 楼主| 发表于 2013-4-13 14:14:12 | 只看该作者
本帖最后由 mdyblog 于 2013-4-13 14:38 编辑
2010qaqz111 发表于 2013-4-13 13:06
_SUB F,* 定义的持久函数是个什么概念?是说这个函数内用 SET& 定义的变量在 _END 后不会销毁,下次进入 ...


》_SUB F,* 定义的持久函数是个什么概念?是说这个函数内用 SET& 定义的变量在 _END 后不会销毁,下次进入该函数其值仍然在,就相当于 c 函数里用 static 定义的变量?
A: 象窗口一样有持久栈,THREAD* 时可以共享其变量。
_SUB   ABC,*
        SET &A=1
        THREAD*  .....
_END
这样 A就是共享变量。而不是拷贝。
同时 ABC 必须保证 子线程 运行期间,A 和含A的栈时可用的,不能销毁了。
这样,运行到 _END处, 标记为已终止, 但会等待子线程结束才真正退出并销毁堆栈。


_SUB   ABC
        SET &A=1
        THREAD*  .....
_END
则不同, 往上找 持久栈,从此处堆栈树分裂,之后的变量为临时变量,全部建一份拷贝。持久栈和以前的变量则共享。
这里 子线程会建立 A的拷贝。
父线程ABC 运行到_END , A 销毁, ABC的堆栈销毁, ABC完全退出。
  
2:
》》》THREAD* 与不加 * 的不同之处在于从窗口的_SUB和,*的_SUB里启动子线程的时候,子线程能否共享上级的变量,是这样吗?
是的。 THREAD*  则共享可共享的变量;还保持窗口的父子关系(链),这样可以象被CALL一样直接访问父窗口及其控件。

3>THREAD
*    有*则共享可共享的变量;还保持窗口的父子关系(链)。否则不共享(除::全局变量),掐断窗口的父子关系链。
&    &表示强制变为PE变量,能最简单变多线程。就是 给子线程 强加了 ENVI^  ForceLocal=1
$    提前解释THREAD 后面的命令, 变量直接变成对应的值。可避免一些延迟解释带来的问题。如%1  %循环变量%
      A=1   //
      LOOP #%&A%<3,
      {         
          THREAD*$ MESS    %A%
          // 解释为THREAD  MESS 1 ,等, 这样不受后面 A=%&A%+1 影响。
          CALC #&A=%&A%+1
      }
+    +为弃儿线程。程序到结尾是不等待该线程退出。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2025-7-23 21:44

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

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