5

ユーザーがUITableViewの行をタップすると、AVAudioPlayerを使用してサウンドを再生しています。行をもう一度タップすると、プレーヤーは停止して破棄されます。曲を最後まで聞くと、FinshedPlaying ハンドラーがプレーヤーを破棄します。

私が抱えている問題は、FinishedPlaying ハンドラーでプレーヤーを破棄しようとすると、次のエラー メッセージが表示されることです。

System.ObjectDisposedException: プレイヤー オブジェクトがコールバック中に Dispose() されました。これにより、プログラムの状態が破損しました

ここにコードがあります、私が間違っていることは何か分かりますか?

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;
        });
    }
}
4

1 に答える 1

6

そこではInvokeOnMainThreadを使用しないでくださいInvokeOnMainThread。入力アクションが完了するのを待ってから呼び出し元に戻るためです。KillAudioPlayerそのため、コールバック内のへの呼び出しの中にいる間に Dispose 呼び出しが発生していHandleAudioFinishedます。

代わりにBeginInvokeOnMainThreadを使用します。これにより、クリーンアップ アクションがメイン スレッドで発生するようにスケジュールされますが、すぐに KillAudioPlayer 関数に戻り、終了できるようになります。

于 2013-05-24T20:50:14.687 に答える