I'm using AVAudioPlayer to play a sound when a user taps a row in a UITableView. If they tap the row again, the player stops and is disposed, and if they listen to the song until it's finished then the FinshedPlaying handler disposes of the player.
The problem I'm having is that when I try to dispose of the player in the FinishedPlaying handler I get the error message:
System.ObjectDisposedException: the player object was Dispose()d during the callback, this has corrupted the state of the program
Here's the code, any idea what I'm doing wrong?
void HandleOnRequestPlayMusic (object sender, UrlEventArgs e)
{
var url = Utils.UrlFromString(e.Url);
string oldUrl = "";
if (musicPlayer != null)
{
oldUrl = musicPlayer.Url.AbsoluteString;
KillAudioPlayer(); // no problems killing the audio player from here
}
if (oldUrl != url.AbsoluteString)
{
musicPlayer = AVAudioPlayer.FromUrl(url);
musicPlayer.FinishedPlaying += HandleAudioFinished;
musicPlayer.Play();
}
}
void HandleAudioFinished (object sender, AVStatusEventArgs e)
{
KillAudioPlayer(); // killing audio player from here causes app to crash
}
void KillAudioPlayer ()
{
if (musicPlayer != null)
{
InvokeOnMainThread(() => {
musicPlayer.Stop();
musicPlayer.FinishedPlaying -= HandleAudioFinished;
musicPlayer.Dispose();
musicPlayer = null;
});
}
}
Don't use InvokeOnMainThread there, because InvokeOnMainThread
waits for the input action to be completed before returning to its caller. That's why your Dispose call is occurring while you're still inside the call to KillAudioPlayer
, inside the HandleAudioFinished
callback.
Instead use BeginInvokeOnMainThread, which will schedule your cleanup action to occur on the main thread, but will return immediately to your KillAudioPlayer function, allowing it to finish.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With