在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
很多时候使用perl多线程可以达到很不错的效果,可以节约很多时间完成很复杂的工作。但通过perl threads模块的描述文件可以看到,它也有很多缺点。比如说在使用perl多线程的时候,必须的保证所有引用的模块都是支持thread。而在实际应用中,我们很难做到这样。比如我们要多线程,但同时要应用OLE模块去操作activex。 此用例应该是一种很常见的用例。那是不是意味着此时我们不得不放弃使用多线程呢。 非也, 本文介绍一种可以使用多线程和ole的例子。 在http://www.cpan.org/官方网站上对这种情况给出的方案是: If the module will only be used inside a thread, you can try loading the module from inside the thread entry point function using sub thr_func { require Unsafe::Module # Unsafe::Module->import(...); .... } If the module is needed inside the main thread, try modifying your application so that the module is loaded (again using 再次,主要讨论一下第二种情况,既主要是该非thread模块放到方法中引用。下面是一个demo。
use threads;
use threads::shared; use Thread::Queue; no warnings 'threads'; # Time out const my $TIMEOUT : shared; $TIMEOUT = 1; # the sig for end thread my $TERM : shared; $TERM = 0; #my $excel; $SIG{'INT'} = $SIG{'TERM'} = sub{ print("\n>>> Terminating <<<\n"); $TERM=1;}; $SIG{'KILL'} = sub{ printf("%3d <- Killed\n", threads->tid()); threads->detach() if !threads->is_detached(); threads->exit(); }; sub ThreadWatcher { my $queue = shift; my %timers; while(!$TERM) { #print "ThreadWatcher -- TERM : $TERM\n"; while(my $tid = $queue->dequeue_nb()) { if (! defined($timers{$tid}{'timeout'} = $queue->dequeue()) || ! defined($timers{$tid}{'thread'} = threads->object($tid))) { # No timeout - unregister thread delete($timers{$tid}); } } foreach my $tid (keys(%timers)) { #print "$timers{$tid}{'thread'} \n"; if(--$timers{$tid}{'timeout'} < 0) { print "thread $timers{$tid}{'thread'} will be killed.\n"; $timers{$tid}{'thread'}->kill('KILL'); delete($timers{$tid}); } } # tick tock sleep(1); } } sub Worker { #eval {use Win32::OLE::Variant;}; my ($queue, $dataqueue) = @_; # get the thread id and register with watch my $tid = threads->tid(); printf("Working -> %3d\n", $tid); $queue->enqueue($tid, $TIMEOUT); print "Worker -- TERM : $TERM\n"; while(!$TERM) { #my $App = $dataqueue->dequeue(); my $data = $dataqueue->dequeue(); #deal with the data #print "Worker -- DATA : $App\n"; print "Worker -- DATA : $data\n"; #my $var = Win32::OLE::Variant->new(VT_BSTR, $data); #print "Worker VAR: $var\n"; } # Remove signal handler $SIG{'KILL'} = sub {}; # Unregister with timer thread $queue->enqueue($tid, undef); # Tell user we're done printf("%3d <- Finished\n", $tid); threads->detach() if ! threads->is_detached(); threads->exit(); } # create time thread my $watchQueue = Thread::Queue->new(); threads->create('ThreadWatcher', $watchQueue)->detach(); # create work thread my $dataQueue = Thread::Queue->new(); threads->create('Worker', $watchQueue, $dataQueue); NoneSafeModelScript('C:\Joe_Chen\Perl_Projects\Threads\update.xlsx'); WairLongTime(10); sub WairLongTime { my $temp = $_[0]; $temp = $temp * 10000000; for(my $index = 0; $index < $temp; $index++) { $index * $index; } return $index; } sub NoneSafeModelScript { eval 'use Win32::OLE'; eval 'use Win32::OLE::Variant'; my $excel; for(my $index = 0; $index < 600; $index++) { print "Getting the Excel ActiveObject. Try # $index \n"; WairLongTime(1); eval { $excel = Win32::OLE->GetActiveObject('Excel.Application') || Win32::OLE->new('Excel.Application', 'Quit'); }; if($@ or $excel == undef) { print "Unsuccessful: $@ \n"; if($index == 599) { print "ERROR:Don\'t got the Excel Application"; } } else { last; } } my $path = $_[0]; my $book = $excel->workbooks->open($path); my $sheet = $book->worksheets(1); my $values = $sheet->Range("A1:D5")->{Value}; my $row_counts = $sheet->Range("A1:C3")->{Rows}->{Count}; my $column_counts = $sheet->Range("A1:C3")->{Columns}->{Count}; print "NoneSafeModelScript : $row_counts \n"; print "NoneSafeModelScript : $column_counts \n"; for(my $row=1; $row<$row_counts + 1; $row++) { my $array_ref = $sheet->Cells($row,1)->{Value}; print "NoneSafeModelScript : $array_ref \n"; my $var = Variant(Win32::OLE::Variant->VT_BSTR, $array_ref); my $v = ref($var); #my $v = $var->Type(); print "NoneSafeModelScript VAR: $var\n"; print "NoneSafeModelScript VAR: $v\n"; #$dataQueue->enqueue($var); $dataQueue->enqueue($array_ref); WairLongTime(2); } my $v = Variant(VT_DATE, "April 1 99"); print $v->Type, "\n"; print $v->Date(DATE_LONGDATE), "\n"; print $v->Date("ddd',' MMM dd yy"), "\n"; print Win32::OLE::Variant->VT_BSTR , "\n"; $book->Close; $excel->Quit; } sub Wrap { my $value = $_[0]; my $var = Variant(VT_DATE, 'Jan 1,1970'); print "Wrap : $var \n"; return $var; }
在此例子中,用到了queue,它的作用是将非thread 安全的数据通过管道传输,这样能避免他们互相调用。 |
请发表评论