gyn

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

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

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

下面是一个例子,用来显示  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 阅读(2069) 评论(0)  编辑 收藏 引用 所属分类: perlTclTk

只有注册用户登录后才能发表评论。
<2008年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

导航

统计

常用链接

留言簿(15)

随笔分类(126)

随笔档案(108)

相册

搜索

最新评论

阅读排行榜

评论排行榜