void HandleNotification(ValueSet valueSet) { //Debug.WriteLine("BackgroundAudioRun.HandleNotification() " + _id); if (_completionSource.Task.IsCompleted) { return; } try { object idValue; if (valueSet.TryGetValue(BackgroundNotificationType.Id, out idValue)) { var id = idValue as Guid?; if (id.HasValue && _appId.HasValue && id.Value != _appId.Value) { Debug.WriteLine("BackgroundAudioRun.HandleNotification() " + _id + " != " + id.Value); return; } } else { Debug.WriteLine("BackgroundAudioRun.HandleNotification() no id " + _id); return; } Guid?appId = null; var isStart = false; var isStop = false; foreach (var kv in valueSet) { //Debug.WriteLine(" f->b {0}: {1}", kv.Key, kv.Value); if (null == kv.Key) { Debug.WriteLine("*** BackgroundAudioRun.HandleNotification() null key"); continue; // This does happen. It shouldn't, but it does. } BackgroundNotificationType type; if (!Enum.TryParse(kv.Key, true, out type)) { continue; } switch (type) { case BackgroundNotificationType.Start: case BackgroundNotificationType.Resume: isStart = true; break; case BackgroundNotificationType.Stop: case BackgroundNotificationType.Suspend: isStop = true; break; case BackgroundNotificationType.Ping: if (_appId.HasValue) { _foregroundNotifier.Notify(BackgroundNotificationType.Pong, kv.Value); } break; case BackgroundNotificationType.Pong: { var challenge = kv.Value as Guid?; if (challenge.HasValue && challenge.Value == _challengeToken.Value) { _challengeCompletionSource.TrySetResult(challenge.Value); } } break; case BackgroundNotificationType.Smtc: if (_appId.HasValue) { SystemMediaTransportControlsButton button; if (Enum.TryParse((string)kv.Value, true, out button)) { var mediaPlayerManager = _mediaPlayerManager; if (null != mediaPlayerManager) { HandleSmtcButton(mediaPlayerManager, button); } } } break; case BackgroundNotificationType.Memory: NotifyForegroundMemory(); break; case BackgroundNotificationType.Gc: var task = Task.Run(() => { MemoryDiagnostics.DumpMemory(); Debug.WriteLine("Force GC: {0:F2}MiB", GC.GetTotalMemory(false).BytesToMiB()); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); Debug.WriteLine("Forced GC: {0:F2}MiB", GC.GetTotalMemory(true).BytesToMiB()); MemoryDiagnostics.DumpMemory(); NotifyForegroundMemory(); }); TaskCollector.Default.Add(task, "Forced GC"); break; case BackgroundNotificationType.Id: var id = kv.Value as Guid?; if (id.HasValue) { appId = id; } break; } } if (!appId.HasValue) { return; } if (_appId.HasValue) { if (appId.Value != _appId.Value) { return; } if (isStop) { _appId = null; } } else { if (isStart) { _appId = appId.Value; } else { return; } } if (isStop) { StopWatchdog(); } else if (!isStart) { ResetWatchdog(); } if (isStart) { SyncNotification(); } } catch (Exception ex) { Debug.WriteLine("BackgroundAudioRun.HandleNotification() " + _id + " failed: " + ex.Message); } }
async Task RunAsync(IBackgroundTaskInstance taskInstance) { BackgroundTaskDeferral deferral = null; BackgroundAudioRun run = null; MemoryDiagnostics.DumpMemory(); var usage = MemoryManager.AppMemoryUsage; var limit = MemoryManager.AppMemoryUsageLimit; if (usage + RequiredMemory > limit) { Debug.WriteLine("*** SmMediaBackgroundAudioTask.RunAsync() low memory"); // We can't play anything because there isn't enough memory. Force // the process to restart. try { Application.Current.Exit(); } catch (Exception ex) { Debug.WriteLine("SmMediaBackgroundAudioTask.RunAsync() exit failed " + ex.ExtendedMessage()); } // Exit() didn't help, so we hog as much as we can of the remaining memory. MemoryHog.ConsumeAllMemory(); BackgroundMediaPlayer.Shutdown(); return; } var deferralId = Guid.NewGuid(); try { Debug.WriteLine("SmMediaBackgroundAudioTask.RunAsync() getting deferral " + deferralId); deferral = taskInstance.GetDeferral(); try { #if DEBUG _memoryDiagnostics.StartPoll(); #endif run = new BackgroundAudioRun(taskInstance.InstanceId); var oldRun = Interlocked.Exchange(ref _run, run); if (null != oldRun) { Debug.WriteLine("SmMediaBackgroundAudioTask.Run() run already exists"); oldRun.Dispose(); } taskInstance.Canceled += run.OnCanceled; taskInstance.Task.Completed += run.OnTaskCompleted; await run.ExecuteAsync().ConfigureAwait(false); } catch (Exception ex) { Debug.WriteLine("SmMediaBackgroundAudioTask.RunAsync() failed " + ex.ExtendedMessage()); } try { #if DEBUG _memoryDiagnostics.StopPoll(); #endif var currentRun = Interlocked.CompareExchange(ref _run, null, run); if (!ReferenceEquals(currentRun, run)) { Debug.WriteLine("SmMediaBackgroundAudioTask.RunAsync() mismatching run"); } if (null != run) { taskInstance.Canceled -= run.OnCanceled; taskInstance.Task.Completed -= run.OnTaskCompleted; } if (null != run) { run.Dispose(); } } catch (Exception ex) { Debug.WriteLine("SmMediaBackgroundAudioTask.RunAsync() cleanup failed: " + ex.ExtendedMessage()); } } finally { if (null != deferral) { deferral.Complete(); Debug.WriteLine("SmMediaBackgroundAudioTask.RunAsync() released deferral " + deferralId); } } }