gyn

Win32下的Perl,无用的select,停滞的Tk,结束吧....

Perl与Tcl/Tk事件驱动的比较

因为在用 Perl-Tk 或者 Socket 时,经常会需要监视某些打开的句柄而不至于阻塞主循环,对于这些 win32 下的 Perl表现远不如Linux下来得得心应手,但这时候我基本没有什么办法。这和windows的底层select实现有关,而Perl恰恰是调用它的,但我一直认为肯定有别的替代办法,因为Tcl/Tkfileevent就表现得很好。

下面是一个例子,用来显示 ping 的结果。这里有两个组件,一个是按钮,用来开始和停止 ping ;另一个是 text 用来显示 ping 的结果。分别用 Perl Tcl/Tk 代码来实现,看看他们有什么不同。

use Tk;

 

$count = 4;

$host = '127.0.01';

 

$mw = MainWindow->new;

 

$bt = $mw->Button(-text => 'Clink to start ping', -command => \&RunPing);

$bt->pack(-fill => 'x');

 

$tx = $mw->Text(-width => 50, -height => 30);

$tx->pack;

 

MainLoop;

 

sub RunPing {

    open $fd, "ping -n $count $host|";

    $mw->fileevent($fd, 'readable' => sub {

       sysread $fd, $buf, 30;

       $tx->insert('end', $buf);

       });

    $bt->configure(-text => 'close', -command => \&ClosePing);

}

 

sub ClosePing {

    close $fd;

    undef $fd;

    $bt->configure(-text => 'Clink to start ping', -command => \&RunPing);

}

运行的结果很让人失望,在 readable 的事件中加入 print 后而已更清楚地看到,事实上 readable 事件是没有被触发过的。这里的 fileevent Tk 中处理事件触发的函数,它为句柄的两个状态( readable writable )设定触发函数,其本质上使用了系统的 select 或者 poll ,换句话说即便是用 Perl select 或者 IO::Seelct 也是于事无补。文档里的原话佐证了这点“ A file is considered to be readable on same basis as the system's select() (or poll()). ”。

所以可以这么讲, win32 下的 Perl 是不大适合处理事件响应的,因而也就很难处理好处理网络相关或者界面需要运行后台长时间操作的情况。接下来换作是使用 Tcl/Tk 来实现这一功能,值得一提的是在 Perl 50 宽度的 button text 是不等长的,所以索性在 pack 里用 fill 自动拓宽了,而在 Tcl/Tk 中没有这个问题。

package require Tk

 

set pingcount 4

set host {127.0.0.1}

 

button .btn -text {Clink to start ping} -command "RunPing $host $pingcount" -width 50

text .text -width 50 -height 30

pack .btn .text

 

proc RunPing {host count} {

    set fd [open "|ping -n $count $host"]

    ;#fconfigure $fd -blocking 0

    fileevent $fd readable "onPingRead $fd $count $host"

    .btn configure -text "close" -command "closeFd $fd $count $host"

}

 

proc onPingRead {fd count host} {

    if {[eof $fd]} {

       closeFd $fd $count $host

    } else {

       set buf [gets $fd]

       .text insert {end} "$buf\n"

    }

}

 

proc closeFd {fd count host} {

    close $fd

    .btn configure -text {Clink to start ping} -command "RunPing $host $count"

}

为了使用同样条件的管道,屏蔽了设置非阻塞的代码行,但这么作 因为系统不得不等待管道中的进程运行结束,所以 也使得 close 没有起到应有的作用。

运行的结果很令人满意, test 没有被阻塞,在显示 ping 结果的同时,依然可以在 text 中执行输入,而且 button 也可以被顺利按下。这么看来 Tcl/Tk 比之 Perl win32 下,显然在事件处理上占有优势,而且这个占优的方面是极其重要的。

posted on 2008-09-20 22:08 gyn_tadao 阅读(240) 评论(0)  编辑 收藏 引用 所属分类: perlTclTk



标题  
姓名  
主页
验证码 *
内容(提交失败后,可以通过“恢复上次提交”恢复刚刚提交的内容)
 
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
[使用Ctrl+Enter键可以直接提交]
 
相关链接:



<2008年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

导航

统计

常用链接

留言簿(3)

随笔分类(99)

随笔档案(82)

相册

搜索

最新评论

阅读排行榜

评论排行榜