UWP MediaPlayer 意外重播音乐
UWP MediaPlayer replays music unexpectedly
我很抱歉,我想让你们帮我调试,但我真的不知道出了什么问题...
所以这是无法按预期工作的代码:
public static async Task SetPlaylist(ICollection<Music> playlist, Music music = null)
{
int index = 0;
if (CurrentPlaylist.Count > 0)
{
if (music == null)
{
CurrentPlaylist.Clear();
PlayBackList.Items.Clear();
}
else
{
Debug.WriteLine(music.Name);
foreach (var item in CurrentPlaylist.ToArray())
{
if (item.Equals(music)) index = 1;
else RemoveMusic(item);
}
Debug.WriteLine(new string('=', 20));
}
}
foreach (var item in playlist.Skip(index))
await AddMusic(item);
if (!CurrentPlaylist.Contains(CurrentMusic))
CurrentMusic = null;
}
这个函数的作用是,它会重置播放列表,如果指定了音乐,则不要从播放列表中删除该音乐。当您还在播放音乐时将音乐播放器设置为随机播放模式时,此功能很有用。它只会在不中断当前播放列表的情况下随机播放播放列表的其余部分。
问题是,如果我在第一个foreach
和运行上设置断点,一步步通过foreach
,那么运行完全没有任何错误。但是,如果我还在第一个foreach
时按continue,那么当前正在播放的音乐会停止并重新开始,这意味着当前正在播放的音乐可能会被删除并重新添加到播放列表中
]
我不知道如何调试它。我只能猜测它可能与 async
有关。它也给出了正确的输出,即使它没有按预期运行。
我的源代码在这里:https://github.com/SeakyLuo/SMPlayer/blob/master/SMPlayer/Helpers/MediaHelper.cs.
我测试了你的代码,发现问题出在SetPlaylist(ICollection<Music> playlist, Music music = null)
方法,可能是频繁remove和add[=导致的16=] 操作,并发生冲突。所以我尝试通过更新数组中的元素来测试,发现它有效,所以你可以用下面的代码试试。
public static async Task SetPlaylist(ICollection<Music> playlist, Music music = null)
{
int index = 0;
foreach (var item in playlist.Skip(1))
{
index++;
await FayAddMusic(item, index);
}
if (!CurrentPlaylist.Contains(CurrentMusic))
CurrentMusic = null;
}
public static async Task FayAddMusic(Music music, int index)
{
try
{
var file = await StorageFile.GetFileFromPathAsync(music.Path);
var source = MediaSource.CreateFromStorageFile(file);
music.IsPlaying = false;
source.CustomProperties.Add("Source", music);
var item = new MediaPlaybackItem(source);
// update element
PlayBackList.Items[index] = item;
CurrentPlaylist[index] = music;
}
catch (System.IO.FileNotFoundException)
{
}
}
感谢@Faywang - MSFT,我知道了重播的原因。虽然他提供的解决方案对我来说似乎不太好,但我非常感谢他的帮助所以我接受了他的回答。
在这里我只是想给出我的解决方案。
首先我创建了另一个 MediaPlaybackList
(我称之为 PendingPlaybackList
)来放置新的随机播放列表。我给它赋值 null
.
然后我没有将所有内容都放在 SetPlaylist
中,而是启动了一个名为 ShuffleOthers
的新函数来执行我想要的操作:
public static async Task SetPlaylist(ICollection<Music> playlist)
{
if (CurrentPlaylist.Count > 0) Clear();
foreach (var item in playlist)
await AddMusic(item);
if (!CurrentPlaylist.Contains(CurrentMusic))
CurrentMusic = null;
}
public static async void ShuffleOthers()
{
PendingPlaybackList = new MediaPlaybackList();
var playlist = ShufflePlaylist(CurrentPlaylist, CurrentMusic);
CurrentPlaylist.Clear();
foreach (var item in playlist)
await AddMusic(item);
CurrentPlaylist[0].IsPlaying = true;
}
调用ShuffleOthers
时,初始化PendingPlaybackList
。而当需要访问PlaybackList
时,通常是当前播放的音乐需要改变的时候,将PendingPlaybackList
到_PlaybackList
之间的所有内容都放入。 _PlaybackList
是 MediaPlayer
的来源
public static MediaPlaybackList PlaybackList
{
get
{
if (PendingPlaybackList != null)
{
if (PendingPlaybackList.Items.Count < _PlaybackList.Items.Count)
return PendingPlaybackList;
_PlaybackList.Items.Clear();
foreach (var item in PendingPlaybackList.Items)
_PlaybackList.Items.Add(item);
PendingPlaybackList = null;
_PlaybackList.MoveTo(0);
}
return _PlaybackList;
}
}
如果我的回答令人困惑,我的源代码是 here。欢迎大家留言。
我很抱歉,我想让你们帮我调试,但我真的不知道出了什么问题...
所以这是无法按预期工作的代码:
public static async Task SetPlaylist(ICollection<Music> playlist, Music music = null)
{
int index = 0;
if (CurrentPlaylist.Count > 0)
{
if (music == null)
{
CurrentPlaylist.Clear();
PlayBackList.Items.Clear();
}
else
{
Debug.WriteLine(music.Name);
foreach (var item in CurrentPlaylist.ToArray())
{
if (item.Equals(music)) index = 1;
else RemoveMusic(item);
}
Debug.WriteLine(new string('=', 20));
}
}
foreach (var item in playlist.Skip(index))
await AddMusic(item);
if (!CurrentPlaylist.Contains(CurrentMusic))
CurrentMusic = null;
}
这个函数的作用是,它会重置播放列表,如果指定了音乐,则不要从播放列表中删除该音乐。当您还在播放音乐时将音乐播放器设置为随机播放模式时,此功能很有用。它只会在不中断当前播放列表的情况下随机播放播放列表的其余部分。
问题是,如果我在第一个foreach
和运行上设置断点,一步步通过foreach
,那么运行完全没有任何错误。但是,如果我还在第一个foreach
时按continue,那么当前正在播放的音乐会停止并重新开始,这意味着当前正在播放的音乐可能会被删除并重新添加到播放列表中
我不知道如何调试它。我只能猜测它可能与 async
有关。它也给出了正确的输出,即使它没有按预期运行。
我的源代码在这里:https://github.com/SeakyLuo/SMPlayer/blob/master/SMPlayer/Helpers/MediaHelper.cs.
我测试了你的代码,发现问题出在SetPlaylist(ICollection<Music> playlist, Music music = null)
方法,可能是频繁remove和add[=导致的16=] 操作,并发生冲突。所以我尝试通过更新数组中的元素来测试,发现它有效,所以你可以用下面的代码试试。
public static async Task SetPlaylist(ICollection<Music> playlist, Music music = null)
{
int index = 0;
foreach (var item in playlist.Skip(1))
{
index++;
await FayAddMusic(item, index);
}
if (!CurrentPlaylist.Contains(CurrentMusic))
CurrentMusic = null;
}
public static async Task FayAddMusic(Music music, int index)
{
try
{
var file = await StorageFile.GetFileFromPathAsync(music.Path);
var source = MediaSource.CreateFromStorageFile(file);
music.IsPlaying = false;
source.CustomProperties.Add("Source", music);
var item = new MediaPlaybackItem(source);
// update element
PlayBackList.Items[index] = item;
CurrentPlaylist[index] = music;
}
catch (System.IO.FileNotFoundException)
{
}
}
感谢@Faywang - MSFT,我知道了重播的原因。虽然他提供的解决方案对我来说似乎不太好,但我非常感谢他的帮助所以我接受了他的回答。
在这里我只是想给出我的解决方案。
首先我创建了另一个 MediaPlaybackList
(我称之为 PendingPlaybackList
)来放置新的随机播放列表。我给它赋值 null
.
然后我没有将所有内容都放在 SetPlaylist
中,而是启动了一个名为 ShuffleOthers
的新函数来执行我想要的操作:
public static async Task SetPlaylist(ICollection<Music> playlist)
{
if (CurrentPlaylist.Count > 0) Clear();
foreach (var item in playlist)
await AddMusic(item);
if (!CurrentPlaylist.Contains(CurrentMusic))
CurrentMusic = null;
}
public static async void ShuffleOthers()
{
PendingPlaybackList = new MediaPlaybackList();
var playlist = ShufflePlaylist(CurrentPlaylist, CurrentMusic);
CurrentPlaylist.Clear();
foreach (var item in playlist)
await AddMusic(item);
CurrentPlaylist[0].IsPlaying = true;
}
调用ShuffleOthers
时,初始化PendingPlaybackList
。而当需要访问PlaybackList
时,通常是当前播放的音乐需要改变的时候,将PendingPlaybackList
到_PlaybackList
之间的所有内容都放入。 _PlaybackList
是 MediaPlayer
public static MediaPlaybackList PlaybackList
{
get
{
if (PendingPlaybackList != null)
{
if (PendingPlaybackList.Items.Count < _PlaybackList.Items.Count)
return PendingPlaybackList;
_PlaybackList.Items.Clear();
foreach (var item in PendingPlaybackList.Items)
_PlaybackList.Items.Add(item);
PendingPlaybackList = null;
_PlaybackList.MoveTo(0);
}
return _PlaybackList;
}
}
如果我的回答令人困惑,我的源代码是 here。欢迎大家留言。