从事件委托更改对象的 属性 时出现错误的线程异常
Wrong Thread Exception when changing an object's property from an event delegate
我有 PlaybackModel
class,我在我的应用程序的 MainPage
中实例化了它,如下所示:
if(PlaybackModel.Current == null) new PlaybackModel();
我使用 PlaybackModel
来存储对我在我的应用程序中使用的对象的引用。它还可以作为大多数页面的 ViewModel。它定义了这些属性,其中包括:
public MediaPlayer player { get; set; }
public MediaPlaybackState playbackState { get; set; }
public RepeatMode repeatMode { get; set; }
public MediaPlaybackList queue { get; set; }
[AlsoNotifyFor("currentIndex", "currentTrack")]
public MediaPlaybackItem currentItem { get; set; }
public ObservableCollection<PlaybackItemViewModel> tracks { get; set; }
public int currentIndex {
get {
return (int)queue.CurrentItemIndex;
} set {
System.Diagnostics.Debug.WriteLine("CurrentIndex Setter called! Value: "+value);
if (value >= 0 && queue.Items.Count() > value && value != queue.CurrentItemIndex)
queue.MoveTo((uint)value);
}
}
public PlaybackItemViewModel currentTrack { get { if (currentIndex == -1) return null; if (tracks.Count() > currentIndex) return tracks[currentIndex]; else return null; } }
private TimeSpan _currentPosition;
public TimeSpan currentPosition { get { return _currentPosition; } set { _currentPosition = value; player.PlaybackSession.Position = _currentPosition; } }
public TimeSpan currentDuration { get; set; }
public Library library { get; set; }
public LastfmClient lastFm { get; set; }
在 PlaybackModel
的检查器中,我订阅了一些事件以跟踪媒体播放器和队列的情况,以便稍后在 UI 中显示它.例如:
player.PlaybackSession.PlaybackStateChanged += (o, ea) =>
{
playbackState = o.PlaybackState;
};
但这行不通。它抛出 WRONG_THREAD
异常。所有这些其他事件都是一样的。我还尝试使用 await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync()
方法来 运行 线程上的代码,但据我了解,当应用程序处于后台播放模式时,这将不起作用。我怎样才能以其他方式做到这一点,以便它支持后台播放?
现在我决定将它用于我的 ItemChanged
活动:
queue.CurrentItemChanged += async (o, ea) =>
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
var pos = currentPosition.Duration();
var bg = App.Ref.IsBackground;
Task<ScrobbleResponse> res = null;
currentPosition = TimeSpan.Zero;
currentItem = o.CurrentItem;
if (ea.OldItem != null)
{
var vm = ea.OldItem.Source.CustomProperties["vm"] as PlaybackItemViewModel;
if (pos.TotalSeconds >= ea.OldItem.Source.Duration.Value.TotalSeconds * 0.9)
{
res = lastFm.Scrobbler.ScrobbleAsync(new Scrobble(vm.Artist, vm.Album, vm.Title, DateTimeOffset.Now));
}
}
if (currentItem != null)
currentDuration = o.CurrentItem.Source.Duration.Value;
else currentDuration = TimeSpan.Zero;
});
};
还有其他方法吗?
谢谢!
调度程序中的代码运行正确。由于条件未在后台更新,因此未调用 if
语句。我的错。
我有 PlaybackModel
class,我在我的应用程序的 MainPage
中实例化了它,如下所示:
if(PlaybackModel.Current == null) new PlaybackModel();
我使用 PlaybackModel
来存储对我在我的应用程序中使用的对象的引用。它还可以作为大多数页面的 ViewModel。它定义了这些属性,其中包括:
public MediaPlayer player { get; set; }
public MediaPlaybackState playbackState { get; set; }
public RepeatMode repeatMode { get; set; }
public MediaPlaybackList queue { get; set; }
[AlsoNotifyFor("currentIndex", "currentTrack")]
public MediaPlaybackItem currentItem { get; set; }
public ObservableCollection<PlaybackItemViewModel> tracks { get; set; }
public int currentIndex {
get {
return (int)queue.CurrentItemIndex;
} set {
System.Diagnostics.Debug.WriteLine("CurrentIndex Setter called! Value: "+value);
if (value >= 0 && queue.Items.Count() > value && value != queue.CurrentItemIndex)
queue.MoveTo((uint)value);
}
}
public PlaybackItemViewModel currentTrack { get { if (currentIndex == -1) return null; if (tracks.Count() > currentIndex) return tracks[currentIndex]; else return null; } }
private TimeSpan _currentPosition;
public TimeSpan currentPosition { get { return _currentPosition; } set { _currentPosition = value; player.PlaybackSession.Position = _currentPosition; } }
public TimeSpan currentDuration { get; set; }
public Library library { get; set; }
public LastfmClient lastFm { get; set; }
在 PlaybackModel
的检查器中,我订阅了一些事件以跟踪媒体播放器和队列的情况,以便稍后在 UI 中显示它.例如:
player.PlaybackSession.PlaybackStateChanged += (o, ea) =>
{
playbackState = o.PlaybackState;
};
但这行不通。它抛出 WRONG_THREAD
异常。所有这些其他事件都是一样的。我还尝试使用 await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync()
方法来 运行 线程上的代码,但据我了解,当应用程序处于后台播放模式时,这将不起作用。我怎样才能以其他方式做到这一点,以便它支持后台播放?
现在我决定将它用于我的 ItemChanged
活动:
queue.CurrentItemChanged += async (o, ea) =>
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
var pos = currentPosition.Duration();
var bg = App.Ref.IsBackground;
Task<ScrobbleResponse> res = null;
currentPosition = TimeSpan.Zero;
currentItem = o.CurrentItem;
if (ea.OldItem != null)
{
var vm = ea.OldItem.Source.CustomProperties["vm"] as PlaybackItemViewModel;
if (pos.TotalSeconds >= ea.OldItem.Source.Duration.Value.TotalSeconds * 0.9)
{
res = lastFm.Scrobbler.ScrobbleAsync(new Scrobble(vm.Artist, vm.Album, vm.Title, DateTimeOffset.Now));
}
}
if (currentItem != null)
currentDuration = o.CurrentItem.Source.Duration.Value;
else currentDuration = TimeSpan.Zero;
});
};
还有其他方法吗?
谢谢!
调度程序中的代码运行正确。由于条件未在后台更新,因此未调用 if
语句。我的错。