AudioPlayerAgent, таймер и веб-сервис - PullRequest
3 голосов
/ 14 марта 2012

мое приложение прочитало shoutcast.

Метаданные воспроизводимой музыки собраны с веб-сервиса, который возвращает мне Json (поэтому мне не нужно декодировать поток). Я вызываю веб-службу каждые 20 секунд с таймером, это работает в моем приложении, но не работает в 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 Ответ

4 голосов
/ 15 марта 2012

Класс AudioPlayer довольно уникален. Он живет только в течение небольшого периода времени. В приложении, которое использует BackgroundAudioPlayer, ваша реализация класса AudioPlayer останется в живых только для выполнения задачи по изменению состояния воспроизведения. Поэтому, когда пользователь начинает что-то воспроизводить, создается экземпляр вашего класса AudioPlayer, чтобы выполнить задачу начала воспроизведения. Как только вы вызываете NotifyComplete () в OnUserAction или OnPlayStateChanged, экземпляр вашего AudioPlayer исчезает.

Фоновый поток, с которым связан AudioPlayer, все еще будет активным, и в этом потоке могут быть живы другие объекты, но AudioPlayer будет прерван. Созданный по умолчанию AudioPlayer намекает на это с помощью поля _classInitialized. Это статично, потому что 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...