Можем ли мы запустить два не вложенных цикла в Perl? - PullRequest
7 голосов
/ 11 марта 2010

Часть моего кода выглядит так:

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. Но длина музыки настолько мала, что она полностью остановится перед тем, как перейти к следующему этапу, поэтому я хочу, чтобы музыка повторялась, но модуль 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?» может быть НЕТ, но я предполагаю, что есть какой-то способ справиться с такой ситуацией. Поправьте меня если я ошибаюсь.

Спасибо как всегда за любые комментарии / предложения:)

UPDATE

Я действительно ценю помощь всех. Спасибо :) Так что ответ на мой вопрос - ДА, а не НЕТ. Я счастлив, что научился использовать fork () и потоки для решения реальной проблемы:)

Ответы [ 3 ]

10 голосов
/ 11 марта 2010

Вы можете запустить два разных процесса в отдельных потоках.

Что-то вроде:

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;
    }
}

ОБНОВЛЕНИЕ

На основеКомментарий Майка ниже, подпрограмма 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;
    }
}
6 голосов
/ 11 марта 2010

Вы можете попытаться раскошелиться, как это:

Таким образом, вы создадите 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 голосов
/ 11 марта 2010

Если ваша сцена 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;
}
...