AudioPlayerAgent, timer and web service

my app read the scream.

Playable music metadata is collected from a web service that returns Json to me (so I don't need to decode the stream). I call the webservice every 20 seconds a timer, this works in my application but does not work in AudioPlayer.cs

//Timer private DispatcherTimer timer; /// <remarks> /// AudioPlayer instances can share the same process. /// Static fields can be used to share state between AudioPlayer instances /// or to communicate with the Audio Streaming agent. /// </remarks> public AudioPlayer() { if (!_classInitialized) { _classInitialized = true; // Subscribe to the managed exception handler Deployment.Current.Dispatcher.BeginInvoke(delegate { Application.Current.UnhandledException += AudioPlayer_UnhandledException; }); } //I activate the timer timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(20) // <------- Error here UnauthorizedAccessException was unhandled. Invalid cross-thread access. }; timer.Tick += timer_Tick; timer.Start(); } private void timer_Tick(object sender, EventArgs e) { HttpWebRequest request = WebRequest.Create("http://127.0.0.81:8003/getmeta") as HttpWebRequest; request.BeginGetResponse(new AsyncCallback(AsyncBack), request); } private void AsyncBack(IAsyncResult ias) { HttpWebRequest req = (HttpWebRequest)ias.AsyncState; try { using (HttpWebResponse res = req.EndGetResponse(ias) as HttpWebResponse) { StreamReader stream = new StreamReader(res.GetResponseStream()); String jsonToParse = stream.ReadToEnd(); JObject jObject = JObject.Parse(jsonToParse); AudioTrack track = BackgroundAudioPlayer.Instance.Track; track.BeginEdit(); track.Title = (string) jObject["title"]; track.Artist = (string) jObject["artist"]; track.Album = (string) jObject["album"]; track.EndEdit(); res.Close(); } } catch (WebException e) { timer.Stop(); } } 

thanks for the help

+3
source share
1 answer

The AudioPlayer class is unique. He lives only for a short period of time. In an application using BackgroundAudioPlayer, the implementation of the AudioPlayer class will only be left alive to complete the task of changing the playback state. So, when the user starts to play something, an instance of your AudioPlayer class will be created to complete the task of starting playback. As soon as you call NotifyComplete () on OnUserAction or OnPlayStateChanged, the instance of your AudioPlayer leaves.

The background stream that AudioPlayer is associated with will still be active, and you may have other objects in that stream, but AudioPlayer will be terminated. The default AudioPlayer hints at this using the _classInitialized field. This is static because AudioPlayer will be created many times, but we only want to sign this event once.

I would suggest one of two things. First, you only need to get json's answer when you need to go to the next song. You will not call NotifyComplete () until the response returns. Here are a few pseudo codes:

 override OnUserAction(BackgroundAudioPlayer player, AudioTrack track, UserAction action, object param) { GetJsonResponse(); } private void GetJsonResponce() { // async call to your service // When async completes: track.BeginEdit(); track.Title = (string) jObject["title"]; track.Artist = (string) jObject["artist"]; track.Album = (string) jObject["album"]; track.EndEdit(); NotifyComplete(); } 

The second is to have a class that does this in the background. This class will have a static property to get an instance that is live in the stream. Then your AudioPlayer will receive the information that it needs from this object.

 public class Songs { static Songs _instance; public static Songs Instance { get { return _instance ?? new Songs(); } } // Do you timer stuff here // Allow the ability to access the timer stuff also. } // in AudioPlayer override OnUserAction(BackgroundAudioPlayer player, AudioTrack track, UserAction action, object param) { Songs.Instance.GetStuff NotifyComplete(); } 
+4
source

Source: https://habr.com/ru/post/971213/


All Articles