从事件委托更改对象的属性时出现错误的线程异常

时间:2017-04-07 20:49:58

标签: c# multithreading events windows-runtime uwp

我有PlaybackModel类,我在我的应用的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()方法在UI线程上运行代码,但据我所知,当应用处于后台播放模式时,这不会起作用。我怎么能以其他方式做到这一点,以便它的工作支持后台播放?

现在我决定将此用于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;
    });
};

还有其他办法吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

调度程序中的代码正确运行。由于条件不在后台更新,因此if语句未被调用。我的坏。