如何仅在第一个结束时播放声音文件?

问题描述:

我有这样的代码:如何仅在第一个结束时播放声音文件?

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

在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