Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我们可以在Perl中同时运行两个非嵌套循环吗?_Perl_Loops_Simultaneous - Fatal编程技术网

我们可以在Perl中同时运行两个非嵌套循环吗?

我们可以在Perl中同时运行两个非嵌套循环吗?,perl,loops,simultaneous,Perl,Loops,Simultaneous,我的部分代码如下所示: while(1){ my $winmm = new Win32::MediaPlayer; $winmm->load('1.mp3'); $winmm->play; $winmm->volume(100); Do Some Stuff; last if some condition is met; } 问题是:当我在while循环中的dosomething阶段时,我希望音乐总

我的部分代码如下所示:

while(1){
        my $winmm = new Win32::MediaPlayer;   
        $winmm->load('1.mp3'); $winmm->play; $winmm->volume(100);
        Do Some Stuff;
        last if some condition is met;
    }
问题是:当我在while循环中的dosomething阶段时,我希望音乐总是打开的。但是音乐的长度很短,在我进入下一个阶段之前,它会完全停止,所以我希望音乐能够自我重复,但是Win32::Mediaplayer模块似乎没有重复模式,所以我考虑对音乐播放部分进行无限循环。像这样:

while(1){
 my $winmm = new Win32::MediaPlayer;   
 $winmm->load('1.mp3'); $winmm->play; $winmm->volume(100);
}
while(2){
Do some stuff;
last if some condition is met
}
但是,根据我目前的Perl知识,如果我是在while(1)部分,我永远不能进入while(2)部分。即使是嵌套循环,我也必须先做一些事情来打破内部循环,然后再转到外部循环的其他部分

我的问题“我们能在Perl中同时运行两个非嵌套循环吗?”的答案可能是否定的,但我认为有某种方法可以处理这种情况。如果我错了,请纠正我

一如既往地感谢您的任何意见/建议:)

更新


我真的很感谢大家的帮助。谢谢:)所以我的问题的答案是肯定的,而不是否定的。我很高兴我学会了如何使用fork()和线程来解决一个真正的问题:)

你可以尝试使用fork,如下所示:

while(1){
        my $winmm = new Win32::MediaPlayer;   
        $winmm->load('1.mp3'); $winmm->play; $winmm->volume(100);
        Do Some Stuff;
        last if some condition is met;
    }
因此,您将创建两个线程,其中一个线程将播放您的音乐,第二个线程将执行所有其他任务

你也应该考虑在某些情况下终止你的音乐线程

    my @child_pids = ();
    my $pid = fork();
    if ($pid)
    {
        # parent
        push(@child_pids, $pid);
        Do some stuff;
        last if some condition is met
    }
    elsif ($pid == 0)
    {
        # child
        while(1){
         my $winmm = new Win32::MediaPlayer;   
         $winmm->load('1.mp3'); $winmm->play; $winmm->volume(100);
        }
        exit(0);
    }
    else
    {
        die "couldn’t fork: $!\n";
    }

您可以在单独的线程中运行这两个不同的进程

大致如下:

use strict;
use warnings;
use threads;
use threads::shared;
use Win32::MediaPlayer;


my $killAudio :shared = undef;
my $audio = threads->create(\&playAudio);
my $condition = threads->create(\&doSomething,$audio);
$condition->join();

sub playAudio {

    my $winmm = new Win32::MediaPlayer;
    $winmm->load('1.mp3') or die 'Could not load file: $!';
    $winmm->volume(100);
    $winmm->play until $killAudio;
}

sub doSomething {
    my $thread = shift;
    my $conditionMet = undef;

    while (1) {
        ($conditionMet,$killAudio) = doSomeStuff();    # set doSomeStuff() to
                                                       # return only when 
                                                       # conditions are met

        $thread->join() if $killAudio;        # This line will terminate $audio
        last if $conditionMet;
    }
}
更新

根据Mike下面的评论,
playAudio()
子例程可以重写为:

sub playAudio {
    my $winmm = new Win32::MediaPlayer;
    $winmm->load('1.mp3') or die 'Could not load file: $!';
    while (1) {
        $winmm->play;
        $winmm->volume(100);
        sleep($winmm->length/1000);
        last if $killAudio;
    }
}
如果你的
doSomething()
阶段自然适合循环结构,你可以周期性地检查歌曲的状态,如果歌曲已经结束,你可以
seek
返回到开始——诚然这是一个黑客行为,但很容易

use strict;
use warnings;

use Win32::MediaPlayer;
my $winmm = Win32::MediaPlayer->new;

$winmm->load($ARGV[0]) or die $!;
$winmm->play;
my $end_of_song = $winmm->length;

# doSomething
for (1 .. 1000){
    # Perform difficult computations...
    sleep 2;

    # Has song ended?
    $winmm->seek(0) if $winmm->pos >= $end_of_song;
}

@用户278023,谢谢,谢谢,这看起来是一个非常好的解决方案:)非常感谢!不客气。我已经稍微更新了代码:现在您可以在必要时使用保存的PID终止父进程中的子进程。@user278023,感谢您的回答,我很高兴我学会了如何使用fork()来解决实际问题。不过,我对这个Win32::Mediaplayer模块有点小问题。为了让音乐重复播放,我必须像这样在while(1)循环中编码:$winmm->load('1.mp3')$winmm->play$winmm->卷(100);睡眠(4);在测试中,音乐持续约4秒,如果没有这条睡眠(4)线,音乐就无法播放。嗯,我很高兴我终于让脚本工作了:)谢谢。@Zaid,这看起来也是解决我问题的一个很有希望的方法。谢谢。我也要试试这个穿线的东西。谢谢:)@Mike:另外,请注意
playAudio()
sub,while循环的每次迭代都不需要创建新的
$winmm
s。我已经更新了代码以反映这一点。@Zaid,多亏了你的回答,我现在学会了如何使用线程来解决实际问题。但是,在使playAudio子功能正常工作时遇到了一些问题。为了让音乐播放,我将sub改为:sub playAudio{my$winmm=new Win32::MediaPlayer;$winmm->load('1.mp3')或die“无法加载文件:$!”;而(1){$winmm->play;$winmm->volume(100);sleep(4);last如果在测试中$killAudio;},音乐持续约4秒。否则,音乐根本无法播放。不管怎样,我很高兴我解决了这个问题。@Mike:不客气!我刚刚看了一下关于CPAN的
Win32::MediaPlayer
模块文档。您可以使用
sleep($winmm->length/1000)
允许代码暂停足够长的时间以播放整个音频文件。(和
use Time::HiRes;
+
usleep($winmm->length);
会有相同的结果)使用Time::hiresqw(usleep)的组合;和usleep($winmm->length);不知怎的,它并没有像预期的那样工作。@Mike:您只需要分配一次
$winmm
,请看下面我的答案。@Zaid,感谢您指出这一点:)+1对于没有线程的解决方案,不需要增加比实际更复杂的复杂性needed@FM,再想想,不,它不符合要求。这首歌在困难的计算结束之前就结束了。我希望这首歌在困难的计算结束之前播放。