我的部分代码是这样的:
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中同时运行两个非嵌套循环吗?”可能是NO,但我认为有一些方法可以处理这种情况。如我错了请纠正我。
一如既往地感谢任何意见/建议:)
更新
我非常感谢大家的帮助。谢谢:)所以我的问题的答案是肯定的,而不是否定的。我很高兴我已经学会了如何使用fork()和线程来解决一个真正的问题:)
答案 0 :(得分: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;
}
}
答案 1 :(得分: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";
}
答案 2 :(得分:2)
如果您的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;
}