首页 文章

在UWP中调用后台任务时,RPC服务器不可用(Excep_FromHResult 0x800706BA)

提问于
浏览
2

我开发了UWP应用程序,它可以在后台或手机锁定时播放音频文件 . 该应用程序工作正常,一切似乎完美5-10分钟 . 之后,当我运行应用程序时,我无法播放音频文件,并且我在主题中附加了异常 . 但是,如果我重新启动应用程序,一切正常 . 我按照以下步骤添加了以下代码和项目来完成任务 .

  • 创建通用项目(Windows Universal)

  • 添加以下代码以发送背景消息

BackgroundMediaPlayer.MessageReceivedFromBackground = BackgroundMediaPlayer_MessageReceivedFromBackground;

  • 添加了具有以下代码的Windows组件运行时(Windows Universal)

  • 在Package.appxmanifest中添加了入口点和后台任务

public sealed class AudioPlayer : IBackgroundTask {
    private BackgroundTaskDeferral deferral;
    private SystemMediaTransportControls systemmediatransportcontrol;
    public void Run(IBackgroundTaskInstance taskInstance) {
        systemmediatransportcontrol = BackgroundMediaPlayer.Current.SystemMediaTransportControls;
        systemmediatransportcontrol.ButtonPressed += systemmediatransportcontrol_ButtonPressed;
        systemmediatransportcontrol.PropertyChanged += systemmediatransportcontrol_PropertyChanged;
        systemmediatransportcontrol.IsEnabled = true;
        systemmediatransportcontrol.IsPauseEnabled = true;
        systemmediatransportcontrol.IsPlayEnabled = true;
        systemmediatransportcontrol.IsNextEnabled = true;
        systemmediatransportcontrol.IsPreviousEnabled = true;

        BackgroundMediaPlayer.Current.CurrentStateChanged += Current_CurrentStateChanged;
        BackgroundMediaPlayer.MessageReceivedFromForeground += BackgroundMediaPlayer_MessageReceivedFromForeground;

        deferral = taskInstance.GetDeferral();

        taskInstance.Canceled += TaskInstance_Canceled;
        taskInstance.Task.Completed += Taskcompleted;
    }
    void Taskcompleted(BackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs args) {
        deferral.Complete();
    }
    private void TaskInstance_Canceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason) {
        try {
            systemmediatransportcontrol.ButtonPressed -= systemmediatransportcontrol_ButtonPressed;
            systemmediatransportcontrol.PropertyChanged -= systemmediatransportcontrol_PropertyChanged;

            BackgroundMediaPlayer.Shutdown(); // shutdown media pipeline
        }
        catch (Exception) {
        }
        deferral.Complete();
    }

    void Current_CurrentStateChanged(MediaPlayer sender, object args) {
        MediaPlayer player = sender;
        switch (player.CurrentState) {
            case MediaPlayerState.Playing:
                systemmediatransportcontrol.PlaybackStatus = MediaPlaybackStatus.Playing;
                break;
            case MediaPlayerState.Paused:
                systemmediatransportcontrol.PlaybackStatus = MediaPlaybackStatus.Stopped;
                break;
        }
    }
    void systemmediatransportcontrol_ButtonPressed(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args) {
        try {
            switch (args.Button) {
                case SystemMediaTransportControlsButton.Play:
                    playTrack();
                    break;
                case SystemMediaTransportControlsButton.Pause:
                    stopBeforePlaying();
                    break;
                case SystemMediaTransportControlsButton.Next:
                    stopBeforePlaying();
                    nextTrack();
                    break;
                case SystemMediaTransportControlsButton.Previous:
                    stopBeforePlaying();
                    previousTrack();
                    break;
            }
        }
        catch (Exception) {
            //Debug.WriteLine(ex.Message);
        }
    }
    void stopBeforePlaying() {
        MediaPlayer player = BackgroundMediaPlayer.Current;
        if (player != null)
            player.Pause();
    }
    void BackgroundMediaPlayer_MessageReceivedFromForeground(object sender, MediaPlayerDataReceivedEventArgs e) {
        object foregroundMessageType;
        if (e.Data.TryGetValue(ApplicationSettingsConstants.ChapterStatus, out foregroundMessageType)) {
            //do something here
        }
    }
    void UpdateUVCOnNewTrack() {
        //update buttons here
    }
    async void playTrack() {
        MediaPlayer player = BackgroundMediaPlayer.Current;
        try {
            if (...) {
                //load track
                player.Play();
            }
            else {
                player.Pause();
                MessageService.SendMessageToForeground(ApplicationSettingsConstants.ChapterStatus, (short)ChapterStatus.ForegroundFileNotFound);
            }
        }
        catch (System.IO.DirectoryNotFoundException) {
            player.Pause();
            MessageService.SendMessageToForeground(ApplicationSettingsConstants.ChapterStatus, (short)ChapterStatus.ForegroundFileNotFound);
        }
        catch (System.IO.FileNotFoundException) {
            player.Pause();
            MessageService.SendMessageToForeground(ApplicationSettingsConstants.ChapterStatus, (short)ChapterStatus.ForegroundFileNotFound);
        }
        finally {
            UpdateUVCOnNewTrack();
        }
    }
    void nextTrack() {
        //load next track
    }
    void previousTrack() {
        //load previous here
    }
}

为什么我收到上述错误?

注意:我已按照Microsoft Sample Background Audio for Windows Phone 8.1 Sample启用后台音频播放器 .

谢谢!

1 回答

  • 1

    某些情况可能会导致BackgroundAudio.Reference中的此异常Windows-universal-samples/Samples/BackgroundAudio/cs/BackgroundAudio/Scenario1.xaml.cs,函数的注释 ResetAfterLostBackground()

    后台任务确实存在,但它已经消失了 . 将前景恢复到初始状态 . 不幸的是,一旦后台任务丢失,任何在BackgroundMediaPlayer.Current上注销事物的尝试都将因RPC错误而失败 .

    因此添加此函数,并在捕获错误的位置调用它 .

    const int RPC_S_SERVER_UNAVAILABLE = -2147023174; // 0x800706BA  
     private void ResetAfterLostBackground()
     {
         BackgroundMediaPlayer.Shutdown();
         try
         {
             BackgroundMediaPlayer.MessageReceivedFromBackground += BackgroundMediaPlayer_MessageReceivedFromBackground;
         }
         catch (Exception ex)
         {
             if (ex.HResult == RPC_S_SERVER_UNAVAILABLE)
             {
                 throw new Exception("Failed to get a MediaPlayer instance.");
             }
             else
             {
                 throw;
             }
         }
     }
    

相关问题