2017-04-04 33 views
1

我有這樣的代碼:如何僅在第一個結束時播放聲音文件?

MediaElement player = new MediaElement(); 
    Windows.Storage.StorageFolder folder; 
    Windows.Storage.StorageFile file; 
    string FileName = ""; 

    private async void Play(string Tno, string Cno) 
    { 
     folder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("Assets"); 

     for (int i = 1; i <= 4; i++) 
     { 
      switch (i) 
      { 
       case 1: 
        FileName = "Sound\\mysound1.wav"; 
        break; 
       case 2: 
        FileName = "Sound\\mysound2.wav"; 
        break; 
       case 3: 
        FileName = "Sound\\mysound3.wav"; 
        break; 
       case 4: 
        FileName = "Sound\\mysound4.wav"; 
        break; 
      } 

      file = await folder.GetFileAsync(FileName); 
      player.SetSource(await file.OpenAsync(Windows.Storage.FileAccessMode.Read), file.ContentType); 
      player.Play(); 
    } 
} 

它播放聲音 「mysound4.wav」。 當我追蹤代碼時,它會過快地播放4個文件,而不會有任何延遲。 那麼我怎樣才能播放第二個文件,只有當第一個完成?

+0

如果是我我會包裹在描述符包裝類持有文件,例如路徑上的數據每個WAV ,持續時間等...將包裝器排隊到知道何時出隊的特殊隊列(您必須記住上次時間項目已過期並檢查持續時間是否已結束)並播放一個項目 – ilansch

+0

嘗試使用Mediaelmement的CurrentState屬性:https ://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.mediaelement#Windows_UI_Xaml_Controls_MediaElement_CurrentState –

+0

如果在多線程環境中調用此方法會怎麼樣?你一次只需要一個媒體播放。 – ilansch

回答

2

在WPF應用的解決方案可以使用這樣的隊列......

public partial class MainWindow : Window 
{ 
    private readonly Queue<string> _audioFilesQueue = new Queue<string>(); 
    private readonly MediaElement _player; 

    public MainWindow() 
    { 
     InitializeComponent(); 

     _player = new MediaElement(); 
     _player.LoadedBehavior = MediaState.Manual; 
     _player.UnloadedBehavior = MediaState.Manual; 
     _player.MediaEnded += Player_MediaEnded; 
    } 

    private void Player_MediaEnded(object sender, RoutedEventArgs e) 
    { 
     OnProcessQueue(); 
    } 

    private void Btn_OnClick(object sender, RoutedEventArgs e) 
    { 
     PlayCascade(new[] 
     { 
      "X:\\Library\\Sounds\\Other\\sound1.wav", 
      "X:\\Library\\Sounds\\Other\\sound2.wav", 
      "X:\\Library\\Sounds\\Other\\sound3.wav" 
     }); 
    } 

    private void PlayCascade(string[] sequence) 
    { 
     foreach (var file in sequence) 
     { 
      _audioFilesQueue.Enqueue(file); 
     } 
     OnProcessQueue(); 
    } 

    private void OnProcessQueue() 
    { 
     Dispatcher.Invoke(() => 
     { 
      if (_audioFilesQueue.Any()) 
      { 
       var toPlay = _audioFilesQueue.Dequeue(); 
       _player.Source = new Uri(toPlay); 
       _player.Play(); 
      } 
     }); 
    } 
+0

隊列是一個非常好的觸摸,但是您應該更加重視回答問題(您的代碼中_really_回答問題的部分是事件回調)。不要誤解我的意思,隊列是爲此而設計的,但這只是質量改進,在這種情況下,它是真正的答案。也許增加2個片段:一個只是解釋回調是如何工作的,另一個是隊列。 – Kroltan

+0

它是真的很好的代碼,謝謝 ,但不幸的是VS 2017不包含MediaState.Manual 所以我評論這些代碼,它沒有工作 _player.LoadedBehavior = MediaState.Manual; _player.UnloadedBehavior = MediaState.Manual; 有什麼建議嗎? – Ammar

+0

這不是VS的問題,我想你不是在WPF應用程序上工作,而是在UWP上工作。然而,我的代碼是指一個WPF桌面應用程序,所以不介意刪除行或適應您的需求 – Grappachu