7

我的部分代码是这样的:

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 循环中的 Do Some Stuff 阶段时,我希望音乐始终打开。但是音乐的长度太短了,在我进入下一个阶段之前它会完全停止,所以我希望音乐自己重复,但是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() 和线程来解决一个真正的问题:)

4

3 回答 3

10

您可以在不同的线程中运行两个不同的进程。

类似于以下内容:

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;
    }
}
于 2010-03-11T08:08:34.373 回答
6

您可以尝试分叉,如下所示:

因此,您将创建 2 个线程,其中一个将播放您的音乐,第二个将执行您的所有其他操作。

您还应该考虑通过某种条件终止您的音乐线程

    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";
    }
于 2010-03-11T08:02:03.207 回答
2

如果您的doSomething()舞台自然地适合循环结构,您可以简单地定期检查歌曲的状态,seek如果歌曲结束,则返回到开头 - 诚然是一个 hack,但很容易。

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;
}
于 2010-03-11T13:40:08.167 回答