我的应用程序读了一个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();
}
}
感谢您的帮助
答案 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();
}