Pergunta

Parte do meu código é assim:

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

O problema é: eu quero que a música seja sempre quando estou no palco fazer alguma coisas no loop while. Mas o comprimento da música é tão curta que ele vai chegar a uma paragem completa antes de eu ir para a próxima fase, então eu quero a música a se repetir, mas o módulo Win32 :: Mediaplayer não parecem ter um modo de repetição, assim que eu estou pensando em fazer um loop infinito para a parte a reprodução de música. Como esta:

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
}

Mas, com base no meu conhecimento atual Perl se eu estou no (1) parte enquanto, eu nunca pode ir para o while (2) parte. Mesmo se se trata de um loop aninhado, eu tenho que fazer alguma coisa para sair do loop dentro antes de ir para a outra parte do circuito exterior.

A resposta à minha pergunta "Podemos executar dois loops não-aninhados simultâneas em Perl?" pode ser um não, mas eu suponho que há alguma maneira de lidar com tal situação. Corrija-me se eu estiver errado.

Graças como sempre para quaisquer comentários / sugestões:)

Atualizar

Eu realmente aprecio a ajuda de todos. Obrigado :) Portanto, a resposta para a minha pergunta é um sim, não um NO. Estou feliz que eu aprendi como usar fork () e tópicos para resolver um problema real:)

Foi útil?

Solução

Você pode executar os dois processos diferentes em segmentos separados.

Algo ao longo das linhas de:

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

Atualizar

Com base no comentário de Mike abaixo, a sub-rotina playAudio() pode ser reescrita como:

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

Outras dicas

Pode tentar garfo, como este:

Assim que você vai criar 2 tópicos, um dos quais irão desempenhar a sua música e segundo vai fazer todas as suas outras coisas.

Você também deve pensar em terminar seu segmento de música por alguma condição

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

Se seus doSomething() estágio se encaixa naturalmente dentro de uma estrutura de loop, você pode simplesmente verificar o status da canção periodicamente e seek volta ao início se a canção terminou -. Reconhecidamente um hack, mas fácil

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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top