我们可以在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,再想想,不,它不符合要求。这首歌在困难的计算结束之前就结束了。我希望这首歌在困难的计算结束之前播放。