音频播放器代理,计时器和Web服务

时间:2012-03-14 13:28:15

标签: c# windows-phone-7 timer windows-phone-7.1 background-process

我的应用程序读了一个shoutcast。

所播放音乐的元数据是从一个返回Json的网络服务中收集的(所以我不需要解码流)。我使用计时器每隔20秒调用一次web服务,这在我的应用程序中有效,但在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();
            }
    }

感谢您的帮助

1 个答案:

答案 0 :(得分:4)

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

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

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

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将从该对象获得所需的信息

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