2013-01-22 3 views
0

컨텍스트 : 미디어 요소를 통해 음악을 재생하고 슬라이더를 사용하여 노래가있는 지점을 표시합니다. 이러한 업데이트는 명백한 이유로 배경 작업자에서 수행됩니다.backgroundworker가 실행되기 전에 완료되었는지 확인

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을 사용하려고했지만 주 스레드는 완료되기 전에 bgPlay.RunWorkerAsync();에 도달했습니다. 당신은 사람이 거의 스레딩과 프로그램 시작 일반적인 실수의 고통

답변

0

하는 race condition

나는이 같은 코드를 재 작성 좋을 걸

: 친절한 끝으로

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 사용을 줄일 수 있습니다.

+0

위대한, 철저한 대답. 고맙습니다! – Wilson

관련 문제