I have a piece of code for checking if a list of media is playable. The problem is that when I run the method and let it finish or cancel it using a CancellationToken
, the MediaPlayer
keeps downloading content and never finishes even though I have a using
and call Dispose()
. Maybe I'm doing something wrong... A little help is very appreciated. Thanks a lot!
Here is the code:
CancellationTokenSource tokenSource = new CancellationTokenSource();
private async Task CheckMediaAsync(CancellationToken token)
{
using (MediaPlayer mediaplayer = new MediaPlayer { IsMuted = true, AutoPlay = true })
{
List<Link> links = DataAccess.GetAllMedia();
for (int i = 0; i < links.Count; i++)
{
mediaplayer.Source = MediaSource.CreateFromUri(new Uri(links[i].LinkMed));
if (await Task.Run(() => CheckUntilTimeout(token, mediaplayer), token))
{
OffileMedia.Add(links[i].Name);
}
if (tokenSource.IsCancellationRequested)
{
mediaplayer.Source = null;
mediaplayer.Dispose();
return;
}
}
mediaplayer.Source = null;
mediaplayer.Dispose();
}
}
private bool CheckUntilTimeout(CancellationToken ct, MediaPlayer mp)
{
Stopwatch stopwatch = Stopwatch.StartNew();
while (stopwatch.Elapsed < TimeSpan.FromSeconds(8))
{
if (ct.IsCancellationRequested)
{
stopwatch.Stop();
return false;
}
if (mp.PlaybackSession.PlaybackState == MediaPlaybackState.None)
{
stopwatch.Stop();
return true;
}
else if (mp.PlaybackSession.PlaybackState == MediaPlaybackState.Playing)
{
stopwatch.Stop();
return false;
}
}
stopwatch.Stop();
return true;
}
Edit:
After some other inspections it seems that the problem is really MediaPlayer
object. If I try to set the Source
as audio streaming for example:
http://icecast.unitedradio.it/Radio105.mp3
http://icecast.unitedradio.it/Virgin.mp3
or any other audio stream, the MediaPlayer
will continue to download each of them even if you set Source
to null or Dispose()
it. Curiously, if try any video stream (m3u8 or mpd)
is seems to work correcty.
You would rather need to dispose underlying MediaSource appropriately to stop downloading besides disposing the MediaPlayer.
So right steps to dispose MediaPlayer currently playing MediaSource created from Uri are...
*Since MediaSource class also has IDisposable interface, it may be better to wrap the code-block in a using(...){ } clause. Then you don't need to call Dispose explicitly.
private async Task CheckMediaAsync(CancellationToken token)
{
using (MediaPlayer mediaplayer = new MediaPlayer { IsMuted = true, AutoPlay = true })
{
List<Link> links = DataAccess.GetAllMedia();
for (int i = 0; i < links.Count; i++)
{
using (MediaSource ms = MediaSource.CreateFromUri(new Uri(links[i].LinkMed)))
{
mediaplayer.Source = ms;
if (await Task.Run(() => CheckUntilTimeout(token, mediaplayer), token))
{
OffileMedia.Add(links[i].Name);
}
mediaplayer.Pause();
mediaplayer.Source = null;
}
if (tokenSource.IsCancellationRequested)
{
//mediaplayer.Source = null;
//mediaplayer.Dispose();
return;
}
}
//mediaplayer.Source = null;
//mediaplayer.Dispose();
}
}