Часть моего кода идет как это:
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;
}
Проблема: Я хочу, чтобы музыка была всегда включена, когда я нахожусь в Некоторого этапа Материала в цикле с условием продолжения. Но длина музыки так коротка, что она прибудет в точку, прежде чем я перейду к следующему этапу, таким образом, я хочу, чтобы музыка повторилась, но 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, если я нахожусь в, в то время как (1) часть, я никогда не могу переходить в в то время как (2) часть. Даже если это приходит к вложенному циклу, я должен сделать что-то для убегания из внутреннего цикла прежде, чем идти в другую часть внешнего цикла.
Ответ на мой вопрос "Мы можем выполнить два одновременных невложенных цикла в Perl?" может быть a нет, но я предполагаю, что существует некоторый способ обработать такую ситуацию. Исправьте меня, если я неправ.
Спасибо как всегда за любые комментарии/предложения :)
ОБНОВЛЕНИЕ
Я действительно ценю справку от всех. Спасибо :) Таким образом, ответ на мой вопрос является a ДА, не НЕТ. Я рад, что изучил, как использовать ветвление () и потоки для решения настоящей проблемы :)
Вы можете запустить два разных процесса в отдельных потоках.
Что-то вроде:
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;
}
}
UPDATE
Основываясь на комментарии Майка ниже, подпрограмму 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;
}
}
Вы можете попробовать выполнить форк, например:
Итак, вы создаст 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";
}
Если ваша сцена doSomething()
естественно вписывается в циклическую структуру, вы можете просто периодически проверять состояние песни и искать
начало, если песня закончилась - конечно, это хак, но простой.
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;
}