Posts Tagged 多线程

Perl中建立一个实例方法的线程

标题有点复杂吧?其实就是新建一个线程,来运行某个对象实例中的特定函数。

一般在Perl中新建一个线程的方法很简单:

  1. use threads;
  2. my $th = threads->create( function_ref, parameters );

但是启动一个实例中的函数就不太一样了,因为不能用 \&$object->method 来取得该函数的引用。

因为自己写脚本的时候有用到,于是花了一个下午探索实验。然后发现一个确实可以work的办法:在一个匿名函数中调用该方法。

不过这个做法实在是丑陋,Perl这样灵活的语言,一定可以有更好的办法来解决这种问题。

实验加翻阅Intermediate perl一个下午还是无果,突然Perl帝出现,看了一眼代码后瞬间给出一个非常正规的解决方法。

具体请直接看示例代码:

下载: cat.pm
  1. package Cat;
  2.  
  3. use strict;
  4. use warnings;
  5.  
  6. sub new {
  7.     my $class = shift;
  8.     my $self = {
  9.         hello => 'Miao',
  10.         @_
  11.     };
  12.     return bless $self, $class;
  13. }
  14.  
  15. sub sayhi {
  16.     my $self = shift;
  17.     my $times = shift || 3;
  18.  
  19.     foreach ( 1 .. $times ) {
  20.         print "$self->{hello}\n";
  21.         sleep 1;
  22.     }
  23. }
  24.  
  25. 1;
下载: sayhi.pl
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5. use threads;
  6. use FindBin qw($Bin);
  7. use lib "$Bin";
  8. use Cat;
  9.  
  10. my $cat = Cat->new( hello => 'meow' );
  11.  
  12. # solution 1: works but ugly
  13. print "\n+++++++ solution 1 +++++++\n";
  14. my $th1 = threads->create( sub { $cat->sayhi(4); } );
  15.  
  16. foreach ( 1 .. 4 ) {
  17.     print "This is main function.\n";
  18.     sleep 1;
  19. }
  20. $th1->join;
  21.  
  22. # solution 2: more professional
  23. print "\n+++++++ solution 2 +++++++\n";
  24. my $th2 = threads->create( \&Cat::sayhi, $cat, 4 );
  25.  
  26. foreach ( 1 .. 4 ) {
  27.     print "This is main function.\n";
  28.     sleep 1;
  29. }
  30. $th2->join;
  31.  
  32. print "\nDemo ends.\n";

, , ,

No Comments

Windows多线程笔记

  最近手头上的东西终于有了一点小突破,这段时间代码上遇到一些问题,有些困了我蛮久。因为之前根本没接触过Windows下面的SDK,Windows核心编程和MSDN都翻了不少,也没少向集训队的学长请教。把这段时间遇到的几个问题整理下,如果能帮到别人就更好了。

子进程的标准输入输出重定向问题:
  没有仔细看MSDN的例子和注释,代码写好后,子进程的标准输入输出还是在父进程的命令行下进行。
  主要原因是 CreateProcess 之前, STARTUPINFO 这个结构不仅仅是指定一下hStdInput, hStdOutput这几个句柄就行了,dwFlags 这个变量需要设置为 STARTF_USESTDHANDLES 才能使以上几个句柄有效。CreateProcess 时,bInheritHandles 需要设置为 TRUE。不仅如此,还有一个容易遗忘的细节,就是 CreateFile 时的 LPSECURITY_ATTRIBUTES 也需要设置为TRUE(同样,CreatePipe 的 SECURITY_ATTRIBUTES 结构的 bInheritHandle 也要设置为TRUE)。

ReadFile堵塞问题:
  如果父进程和子进程通过匿名管道来通信,且把子进程的标准输入输出重定向到了管道,那么会碰到下面这个问题。当子进程的输出被存在缓冲区内,没有刷新的话,管道中就一直没有数据,这时候如果用ReadFile读取管道中的数据则ReadFile被堵塞,于是父进程也被堵塞。目前我还没找到在不修改子进程代码的情况下解决这个问题的办法。只能用不使用缓冲区的输出函数来解决。
  但是如果子进程确实没有输出,那么还是有办法防止父进程被堵塞的,就是事先用 GetFileSize 来检查管道文件容量是否为0。还有一个办法是使用异步I/O来完成通信。

ReadFile读取控制:
  如果父进程在一个工作流程中,只需要从子进程发回的信息中读取一行的话,则只让ReadFile读取一个字符的数据,直到碰到换行符为止,Windows下文件的换行符为”\r\n”。

,

No Comments