0

コンテキスト:メディア要素を介して音楽を再生し、スライダーを使用して曲のポイントを表示しています。その更新は、明らかな理由で、バックグラウンドワーカーで行われます。

private void bgPlay_DoWork(object sender,DoWorkEventArgs e)
    {

        while (isMediaPlaying)
        {
            this.Dispatcher.Invoke((Action)(() =>
            {
                timelineSlider.Value = mediaElement1.Position.TotalMilliseconds;
            }));

        }
    }

    private void Library_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        try
        {
            mediaElement1.Stop();
            isMediaPlaying = false;
            mediaElement1.Source = new Uri(songData[Library.SelectedIndex].Location);
            mediaElement1.Volume = (double)volumeSlider.Value;

            mediaElement1.Play();

            isMediaPlaying = true;

            bgPlay.RunWorkerAsync();
        }
        catch(Exception ex) {
            F.MessageBox.Show(ex.ToString());
        }
    }

曲を再生してから別の曲をダブルクリックすると、バックグラウンドワーカーはループを続けbgPlay.RunWorkerAsync();、前のインスタンスが終了する前に到達したため、例外をスローします。isMediaPlaying boolを使用して、ループを終了するタイミングをbackgroundworkerに通知しようとしましたが、メインスレッドがbgPlay.RunWorkerAsync();終了する前に到達します。

4

1 に答える 1

0

競合状態であるスレッディングを使用してプログラムを開始することがほとんどない場合、よくある間違いに苦しんでいます。

次のようにコードを書き直すことをお勧めします。

private static String threadingLock = "";

private void bgPlay_DoWork(object sender,DoWorkEventArgs e)
    {

        while (true)
        {
            lock(threadingLock) {
                if(!isMediaPlaying)
                    break;
            }
            this.Dispatcher.Invoke((Action)(() =>
            {
                timelineSlider.Value = mediaElement1.Position.TotalMilliseconds;
            }));

        }
    }

    private void Library_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        try
        {
            lock(threadingLock) {
                isMediaPlaying = false;
            }
            mediaElement1.Stop();

            mediaElement1.Source = new Uri(songData[Library.SelectedIndex].Location);
            mediaElement1.Volume = (double)volumeSlider.Value;

            mediaElement1.Play();

            isMediaPlaying = true;

            bgPlay.RunWorkerAsync();
        }
        catch(Exception ex) {
            F.MessageBox.Show(ex.ToString());
        }
    }

わかりやすいヒントとしてThread.sleep(200)、スライダーで更新を呼び出す前にを追加してください。アプリケーションの機能に影響を与えることなく、CPU使用率を削減します。

于 2013-01-22T23:38:37.173 に答える