在这个程序中POE :: Wheel :: FollowTail适用于跟踪文件的尾部,它也在一个单独的线程中运行,只是监视编译作业的进度。
在InputEvent处理程序中有一个粗糙的正则表达式来提取编译结果,并且一切正常,但是我无法获得任何结果值,可以在此sub之外访问。即使我将结果变量放在全局范围内,也不会修改它们。
该程序包括一个运行编译作业的进程,另一个正在查看日志,以及主循环等待。
全球范围:
my $Pass = 0;
my $Done = 0;
然后启动监控:
threads->create(\&StartWatcher);
watch-log文件sub的位置如下:
sub StartWatcher
{
my $logfile = "filename.log";
# Create the logfile watcher
POE::Session->create
(
inline_states =>
{
_start => sub
{
$_[HEAP]{tailor} = POE::Wheel::FollowTail->new( Filename => $logfile, InputEvent => "got_log_line", );
},
got_log_line => sub
{
$Pass += () = $_[ARG0] =~ /^\d+.*vcproj \- 0 error\(s\), \d+ warning\(s\)/g;
$Done += () = $_[ARG0] =~ /^\d+.*vcproj \- \d+ error\(s\), \d+ warning\(s\)/g;
print "POE InputEvent Pass: $Pass, Done: $Done\n"; # Debug output
},
}
);
POE::Kernel->run();
}
$ logfile是由使用Win32 :: Process :: Create启动的Visual Studio编译作业编写的,主要的Perl执行位于此循环中,等待编译器终止,并每秒生成一次状态输出。 / p>
while('true')
{
$ProcessObj->Wait(100); # milliseconds wait
$ProcessObj->GetExitCode($exitcode);
if ( $exitcode == STILL_ACTIVE )
{
"Compiling... [$Done/$Count] Pass: $Pass Failed: $failed"
if($RunCounter++ % 10 == 0);
next;
}
last;
}
产生的输出类似于:
POE InputEvent Pass: 1, Done: 1
Compiling... [0/91] Pass: 0 Failed: 0
即。在InputEvent处理程序got_log_line中,两个全局变量已经递增,但在Perl主循环中它们仍然为零。我意识到我可以从InputEvent处理程序执行打印输出,但为什么不修改全局变量?
出了什么问题?
答案 0 :(得分:5)
perl中的线程与其他语言的工作方式不同,程序空间不共享。在线程创建中,当前线程被复制到新线程中,该线程与父线程分离(每个线程都有自己的perl解释实例)。如果你想在线程之间进行通信,请查看threads :: shared,Thread :: Queue和Thread :: Semaphore。
答案 1 :(得分:0)
根据上述任何建议,以下是答案:
在启动线程之前,创建一个共享队列
use threads;
use Thread::Queue;
use threads::shared;
my $queue:shared = Thread::Queue->new();
在输入事件中,创建一些共享数据以入队
my %data:shared = ();
$data{PASS_VCPRJ_COUNT} = () = $_[ARG0] =~ /^\d+.*vcproj.*0 error.*\d+ warning/g;
$data{DONE_VCPRJ_COUNT} = () = $_[ARG0] =~ /^\d+.*vcproj.*d+ error.*\d+ warning/g;
$queue->enqueue(\%data) if($data{DONE_VCPRJ_COUNT} ne 0 || $data{PASS_VCPRJ_COUNT} ne 0);
然后在屏幕更新代码中,将其出列,此处为非阻塞
if (defined(my $item = $queue->dequeue_nb()))
{
foreach my $key(%$item)
{print "$key $item->{$key}\n";}
}
还有其他方法,我敢肯定,但这对我有用。 非常感谢。