请选择 进入手机版 | 继续访问电脑版

 找回密码
 立即注册
查看: 6058|回复: 13

分享个自定义封装的进程通信库processcmd

[复制链接]

26

主题

139

帖子

490

积分
交易币
172

超级版主

Rank: 8Rank: 8

发表于 2015-4-18 12:08:45 | 显示全部楼层 |阅读模式
本帖最后由 carl 于 2015-4-20 11:51 编辑

processcmd 进程通信库,是对process.command标准库做了二次封装,主要以 进程ID 做为通信依据

[aardio] 纯文本查看 复制代码
//processcmd 进程通信
namespace carl

processcmd = class {
        ctor( guid, ... ){
                var cmdline = _CMDLINE;
                var owerPid = process.getId();
                if( !guid ){
                        guid = win.guid.create();
                        guid = string.upper( tostring(guid) );
                }
                if( #cmdline ){
                        if(cmdline[1] == '{'# ) {
                                var t = eval(cmdline);
                                guid = t.guid;
                                this.parentPid = t.parentPid;//父进程ID
                        }else {
                                return null,"不是有效参数"; 
                        }
                }
                var mutex,err = process.command.join(guid);//加入进程群组
                if(!mutex) error(err,2);
                
                this.pids = thread.table("table" + guid);
                this.guid = guid;
                this.serverCmd = process.command( ... );//注册进程命令对象
                
                if( !..thread.get(guid) ) {
                        ..thread.set(guid, true)
                        
                        this.serverCmd.receive = function( t ) { //接收命令
                                if( (t.toPid && t.toPid != owerPid) || (!t.toPid && !this.parentPid) )
                                        return ;
                                if( type.table == type(t.msg) ){
                                        if( this.parentPid ){
                                                if( type(this.receiveChild) != type.function )
                                                        error("请先定义receiveChild消息处理函数",2);
                                                return this.receiveChild(t.fromPid, table.unpackArgs(t.msg))
                                        }else {
                                                if( type(this.receiveParent) != type.function )
                                                        error("请先定义receiveParent消息处理函数",2);
                                                return this.receiveParent(t.fromPid, table.unpackArgs(t.msg))
                                        }
                                }
                        }
                        
                        this.serverCmd.quit = function( fromPid ) { 
                                if( fromPid == owerPid || (!fromPid && this.parentPid))
                                        win.quitMessage(0);
                        }
                }
        };

        sendto = function( toPid, types, ... ) {
                var t = {};
                t.fromPid = owerPid;
                t.toPid = toPid;
                t.msg = {...};
                if( types == "send" ){
                        return process.command.send("receive",t);
                }
                elseif( types == "post" ){
                        return process.command.post("receive",t);
                }
                elseif( types == "quit" ){
                        process.command.post("quit",toPid);
                }
        }
        
        send = function( toPid, ...) {
                return this.sendto( toPid, "send",...)
        }
        
        post = function( toPid, ...) {
                return this.sendto( toPid, "post", ... )
        }
        
        create = function( exepath ) {
                if( _STUDIO_INVOKED )        error("请先发布,才能创建子进程");
                exepath := ..io._exepath;
                var t = {}
                t.guid = guid;
                t.parentPid = owerPid;
                var pro = process(exepath, table.tostring(t));//命令参数 cmd
                this.pids.push(pro.id)
                delay(1000)
                return pro.id;
        }
                
        quit = function( toPid ) {
                this.sendto( toPid, "quit" );
        }
        
        kill = function( toPid ) {
                try{
                        if( toPid ){
                                process.kill(toPid);
                        }else {
                                for( i,pid in this.pids.each() ){
                                         process.kill(pid);
                                }        
                        }
                }
        }
        
        waitClose = function(pid){
                var bool;
                while(true){
                        bool = false;
                        if(pid){
                                if( process.getPath(pid) ) bool = true;
                        }
                        else {
                                for( i,pid in this.pids.each() ){
                                        if(process.getPath(pid)){
                                                bool = true;
                                                break ;
                                        }
                                }
                        }
                        if(!bool || !delay(1000)) break ;
                }
        }
}

namespace processcmd{
        import win;
        import win.guid;
        import process;
        import process.command;
        import thread.table;

        table = ..table;
        string = ..string;
        delay = ..win[["ui"]] ?  ..win[["delay"]] : sleep;
}

/**intellisense()
carl.processcmd = 进程通信库
carl.processcmd() = 创建进程通信对像,第一次创建,参数:进程群组Guid,可忽略,创建成功后,可以用 对像.guid 读取
carl.processcmd(guid) = 创建进程通信对像,参数:进程群组Guid不可忽略,可传入第一次创建的guid
?carl.processcmd = !cmd.
!cmd.create() = 创建本身做为子进程,返回子进程ID;
!cmd.create(.(子进程路径)) = 创建子进程,参数:子进程路径,返回子进程ID;
!cmd.send(.(进程ID,消息内容)) = 阻塞调用跨进程命令,参数一:可指定进程ID,忽略则向所有子进程发消息,\n可获取处理该命令的回调函数返回值,\n用于父进程与子进程之间通信,或子进程与子进程之间通信
!cmd.post(.(进程ID,消息内容)) = 非阻塞调用跨进程命令,参数一:可指定进程ID,忽略则向所有子进程发消息,\n无返回值,\n用于父进程与子进程之间通信,或子进程与子进程之间通信
!cmd.receiveParent = @.receiveParent = function( fromPid,... ) {
        /*如果当前进程是父进程,此函数用于接收来至其他进程发的消息,回调参数:发送方进程ID,不定个数参数*/
        __/*进程里第一次最先定义此函数的地方有效,其他地方无效*/
}
!cmd.receiveChild = @.receiveChild = function( fromPid,... ) {
        /*如果当前进程是子进程,此函数用于接收来至其他进程发的消息,回调参数:发送方进程ID,不定个数参数*/
        __/*进程里第一次最先定义此函数的地方有效,其他地方无效*/
}
!cmd.quit(.(进程ID)) = 退出一个子进程,发送win.quitMessage()退出消息
!cmd.quit() = 退出所有子进程,发送win.quitMessage()退出消息
!cmd.kill(.(进程ID)) = 强制杀死子进程
!cmd.kill() = 强制杀死所有子进程
!cmd.serverCmd = 进程命令对象
!cmd.parentPid = 父进程ID,如果值为null,说明当前进程是父进程
!cmd.guid = 进程群组Guid
!cmd.pids = 所有子进程ID表table对像
!cmd.waitClose() = 等待所有子进程退出
!cmd.waitClose(pid) = 等待指定子进程退出,参数子进程ID
end intellisense**/


例子
[aardio] 纯文本查看 复制代码
import win.ui;
import carl.processcmd
/*DSG{{*/
var winform = ..win.form(text="aardio Form";right=442;bottom=242)
winform.add(
btnCreate={cls="button";text="先创建一个子进程";left=16;top=17;right=160;bottom=50;z=2};
btnReply={cls="button";text="回复";left=335;top=66;right=424;bottom=96;z=5};
btnSend={cls="button";text="发送";left=234;top=67;right=323;bottom=97;z=3};
edit={cls="edit";left=22;top=104;right=421;bottom=227;edge=1;multiline=1;z=1};
edit2={cls="edit";text="大家好";left=21;top=71;right=219;bottom=100;edge=1;multiline=1;z=4}
)
/*}}*/

cmd = carl.processcmd();
if(!cmd) return ; 

cmd.receiveParent = function( fromPid,... ) {
        /*如果当前进程是父进程,此函数用于接收来至其他进程发的消息,回调参数:发送方进程ID,不定个数参数*/
        winform.edit.appendText("我是父进程,收到消息",fromPid,...,'\r\n')
}

cmd.receiveChild = function( fromPid,... ) {
        /*如果当前进程是子进程,此函数用于接收来至其他进程发的消息,回调参数:发送方进程ID,不定个数参数*/
        winform.edit.appendText("我是子进程,收到消息",fromPid,...,'\r\n')
}

winform.btnSend.oncommand = function(id,event){
        cmd.post(,winform.edit2.text);//发送给所有子进程
}

winform.btnReply.oncommand = function(id,event){
        cmd.post(cmd.parentPid,winform.edit2.text);//回复父进程
}

winform.btnCreate.oncommand = function(id,event){
        childPid = cmd.create()//创建本身做为子进程
}

if(cmd.parentPid){//值为true,说明当前是子进程
        winform.btnSend.disabled = true
        winform.btnCreate.disabled = true
        winform.text = "我是子进程" ++ process.getId()
}else {//值为null,说明当前进程是父进程
        winform.btnReply.disabled = true
        winform.text = "我是父进程" ++ process.getId()
}


winform.show() 
win.loopMessage();


cmd.png


processcmd 进程通信库下载,请解压于目录 /lib/carl/processcmd.aau
processcmd.rar (1.92 KB, 下载次数: 203)
回复

使用道具 举报

15

主题

56

帖子

127

积分
交易币
0

编程一段

Rank: 2

发表于 2015-4-18 12:20:17 | 显示全部楼层
赞  学习下 谢谢
回复 支持 反对

使用道具 举报

2

主题

38

帖子

159

积分
交易币
0

编程一段

Rank: 2

发表于 2015-4-18 12:59:06 来自手机 | 显示全部楼层
谢谢分享,下载学习
回复 支持 反对

使用道具 举报

19

主题

123

帖子

243

积分
交易币
0

编程二段

Rank: 3Rank: 3

发表于 2015-4-20 13:29:14 | 显示全部楼层
厉害,果然出手不同。收藏学习了
回复 支持 反对

使用道具 举报

4

主题

14

帖子

37

积分
交易币
0

新手入门

Rank: 1

发表于 2015-5-4 20:53:22 | 显示全部楼层
老大威武啊,好多干货。收藏
回复 支持 反对

使用道具 举报

11

主题

61

帖子

182

积分
交易币
16

版主

Rank: 7Rank: 7Rank: 7

发表于 2015-5-5 09:01:19 | 显示全部楼层
发现一个小问题,如下代码运行时先打开一个ie进程,然后点击“先创建子进程”按钮,弹出子进程,但同时又弹出一个ie进程。

另外,代码里写io.open()打开控制台,创建子进程后为何不会重新再打开一个控制台呢?

[aardio] 纯文本查看 复制代码
import win.ui;
import carl.processcmd
/*DSG{{*/
var winform = ..win.form(text="aardio Form";right=442;bottom=242)
winform.add(
btnCreate={cls="button";text="先创建一个子进程";left=16;top=17;right=160;bottom=50;z=2};
btnReply={cls="button";text="回复";left=335;top=66;right=424;bottom=96;z=5};
btnSend={cls="button";text="发送";left=234;top=67;right=323;bottom=97;z=3};
button={cls="button";text="button";left=225;top=17;right=336;bottom=46;z=6};
button2={cls="button";text="button2";left=344;top=15;right=435;bottom=46;z=7};
edit={cls="edit";left=22;top=104;right=421;bottom=227;edge=1;multiline=1;z=1};
edit2={cls="edit";text="大家好";left=21;top=71;right=219;bottom=100;edge=1;multiline=1;z=4}
)
/*}}*/


cmd = carl.processcmd();
if(!cmd) return ; 
cmd.create("C:\Program Files\Internet Explorer\iexplore.exe");


cmd.receiveParent = function( fromPid,... ) {
        /*如果当前进程是父进程,此函数用于接收来至其他进程发的消息,回调参数:发送方进程ID,不定个数参数*/
        winform.edit.appendText("我是父进程,收到消息",fromPid,...,'\r\n')
}
 
cmd.receiveChild = function( fromPid,... ) {
        /*如果当前进程是子进程,此函数用于接收来至其他进程发的消息,回调参数:发送方进程ID,不定个数参数*/
        winform.edit.appendText("我是子进程,收到消息",fromPid,...,'\r\n')
}
 
winform.btnSend.oncommand = function(id,event){
        cmd.post(,winform.edit2.text);//发送给所有子进程
}
 
winform.btnReply.oncommand = function(id,event){
        cmd.post(cmd.parentPid,winform.edit2.text);//回复父进程
}
 
winform.btnCreate.oncommand = function(id,event){
        childPid = cmd.create()//创建本身做为子进程
}
 
if(cmd.parentPid){//值为true,说明当前是子进程
        winform.btnSend.disabled = true
        winform.btnCreate.disabled = true
        winform.text = "我是子进程" ++ process.getId()
}else {//值为null,说明当前进程是父进程
        winform.btnReply.disabled = true
        winform.text = "我是父进程" ++ process.getId()
}
 
 
winform.show() 
win.loopMessage();
回复 支持 反对

使用道具 举报

26

主题

139

帖子

490

积分
交易币
172

超级版主

Rank: 8Rank: 8

 楼主| 发表于 2015-5-5 09:27:39 | 显示全部楼层
M31 发表于 2015-5-5 09:01
发现一个小问题,如下代码运行时先打开一个ie进程,然后点击“先创建子进程”按钮,弹出子进程,但同时又弹 ...

你这是打开外部进程IE,你每开一个子进程都在开始端打开一个IE进程,当然都会出现IE了,
这个库的本意是用这通信用的,是指针对打开aau发布的程序可以交互通信,你打开外部程序这跟process.execute打开无差别的,跟外部程序肯定不能互相交互的,

如果是用本身做为子进程是用cmd.parentPid这个值来判断自己是子进程,还是父进程的,
回复 支持 反对

使用道具 举报

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

本版积分规则



GMT+8, 2019-10-23 16:58 , Processed in 0.140625 second(s), 28 queries .

© 2001-2011 Powered by Discuz! X3.2.

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