7

私のコードの一部は次のようになります:

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ループのDoSomeStuffステージにいるときに音楽を常にオンにしたいということです。しかし、音楽の長さが非常に短いため、次のステージに進む前に完全に停止するので、音楽を繰り返してほしいのですが、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で2つのネストされていないループを同時に実行できますか?」いいえかもしれませんが、そのような状況に対処する方法があると思います。私が間違っている場合は私を訂正してください。

コメント/提案をいつもありがとう:)

アップデート

皆様のご協力に心より感謝申し上げます。ありがとう:)だから私の質問への答えはイエスであり、ノーではありません。fork()とスレッドを使用して実際の問題を解決する方法を学んだことをうれしく思います:)

4

3 に答える 3

10

2 つの異なるプロセスを別々のスレッドで実行できます。

次のようなもの:

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;
    }
}
于 2010-03-11T08:08:34.373 に答える
6

次のように fork を試みることができます。

そのため、2 つのスレッドを作成します。そのうちの 1 つは音楽を再生し、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";
    }
于 2010-03-11T08:02:03.207 に答える
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;
}
于 2010-03-11T13:40:08.167 に答える