AudioPlayerAgent, timer and webservice

巧了我就是萌 提交于 2019-12-17 16:51:41

问题


my application read a shoutcast.

The meta data of the music played is collected from a webservice that return me a Json (so i don't have to decode the stream). I call the webservice every 20 seconds with a timer, this works in my application, but doesn't works in the 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 you for the help


回答1:


The AudioPlayer class is quite unique. It only lives for a small period of time. In an application that uses the BackgroundAudioPlayer, yous implementation of the AudioPlayer class will only stay alive to accomplish the task of changing play state. So, when a user begins playing something, an instance of your AudioPlayer class will be created to accomplish the task of begin playing. Once you call NotifyComplete() within the OnUserAction or OnPlayStateChanged, the instance of your AudioPlayer goes away.

The background thread that the AudioPlayer is associated with will still be active and you can have other objects alive within that thread, but the AudioPlayer will be terminated. The default AudioPlayer that is created hints at this with the _classInitialized field. This is static because the AudioPlayer will be created many times, but we only want to subscrrbe to that event once.

I would suggest one of two things. The first is to only get the json response when you need to advance to the next song. You would not call NotifyComplete() until after the response has returned. Here is some pseudo code:

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 would be to have a class that does this in the background. That class would have a static property to get the instance that is alive in the thread. Then your AudioPlayer would get the info it needs from that 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();
}


来源:https://stackoverflow.com/questions/9702935/audioplayeragent-timer-and-webservice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!