AudioPlayerAgent、定时器和网络服务 [英] AudioPlayerAgent, timer and webservice

查看:15
本文介绍了AudioPlayerAgent、定时器和网络服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序读取了一个声音广播.

my application read a shoutcast.

播放音乐的元数据是从返回 Json 的网络服务中收集的(因此我不必解码流).我每 20 秒用一个计时器调用一次网络服务,这在我的应用程序中有效,但在 AudioPlayer.cs 中无效

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();
            }
    }

感谢您的帮助

推荐答案

AudioPlayer 类非常独特.它只存活一小段时间.在使用 BackgroundAudioPlayer 的应用程序中,AudioPlayer 类的实现只会保持活动状态以完成更改播放状态的任务.因此,当用户开始播放某些内容时,将创建 AudioPlayer 类的一个实例来完成开始播放的任务.一旦您在 OnUserAction 或 OnPlayStateChanged 中调用 NotifyComplete(),您的 AudioPlayer 实例就会消失.

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.

与 AudioPlayer 相关联的后台线程仍将处于活动状态,您可以在该线程中让其他对象处于活动状态,但 AudioPlayer 将被终止.创建的默认 AudioPlayer 使用 _classInitialized 字段提示这一点.这是静态的,因为 AudioPlayer 将被创建多次,但我们只想订阅该事件一次.

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.

我会建议两件事之一.第一个是只在需要前进到下一首歌曲时才获得 json 响应.在响应返回之前,您不会调用 NotifyComplete().下面是一些伪代码:

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();
}

第二种是有一个在后台执行此操作的类.该类将有一个静态属性来获取线程中活动的实例.然后您的 AudioPlayer 将从该对象中获取所需的信息

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();
}

这篇关于AudioPlayerAgent、定时器和网络服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆