Как остановить SoundEffect от сбоя игр XNA Windows, когда они закрыты? - PullRequest
4 голосов
/ 24 февраля 2011

Я создаю игру для Windows в XNA, используя Visual C # Express.В игре есть шесть объектов SoundEffect, для которых регулярно вызываются методы Play ().Проблема в том, что иногда, когда игра закрывается, она падает. Похоже, это происходит всякий раз, когда окно закрывается во время воспроизведения звукового эффекта. Это сообщение, которое появляется в Visual C #:

AccessViolationException не обрабатывалось

Попытка чтения или записи в защищенную память.Это часто указывает на то, что другая память повреждена.

В Visual Studio нет доступных источников для отладки, и когда нажимается «получить общую справку по этому исключению», появляется пустая страницаup ..

Используемый код очень похож на пример MSDN.Это похоже на проблему, которая существует где-то в базовой структуре, а не на мой код.Но, конечно, я не знаю наверняка.Это случалось много раз.

http://msdn.microsoft.com/en-us/library/bb195053.aspx

Вот полная информация об исключении:

System.AccessViolationException was unhandled
  Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
  Source=Microsoft.Xna.Framework
  StackTrace:
       at Microsoft.Xna.Framework.Audio.AudioCallbackDispatcher.IsEventRegistered(EventType type)
       at Microsoft.Xna.Framework.Audio.AudioCallbackDispatcher.UnregisterEvent(EventType type)
       at Microsoft.Xna.Framework.Audio.KernelMicrophone.ShutdownCaptureEngine()
       at Microsoft.Xna.Framework.Audio.MicrophoneUnsafeNativeMethods.ShutdownCaptureEngine()
       at Microsoft.Xna.Framework.Audio.AudioRendererShutdownHandler.AppExitingEventHandler(Object sender, EventArgs args)
  InnerException:

(у меня также играет музыка через MediaPlayer, но я не думаю, что этосвязанный.)

РЕДАКТИРОВАТЬ: Кажется, я нашел что-то, что работает, но это вроде хакерской и действительно не должно быть необходимости.Я все еще открыт для любых более изящных решений.

Вызовите эту строку в Game1.UnloadContent ().Он будет убедиться (если ваши звуковые эффекты короче 3 секунд), что звук не воспроизводится, когда программа действительно закрывается.

System.Threading.Thread.Sleep(3000);

Ответы [ 4 ]

2 голосов
/ 24 февраля 2011

Сделайте объект SoundEffect членом класса и вызовите метод Dispose () SoundEffect для деконструкции класса:

class MyClass
{
    ~MyClass()
    {
        effect.Dispose();
    }

    SoundEffect effect;

}

Это должно позволить объекту SoundEffect очиститься при закрытии игры. Вы можете прочитать об объектах, которые одноразовые, здесь: http://msdn.microsoft.com/en-us/library/system.idisposable.aspx

1 голос
/ 25 февраля 2011

Я думаю, что можно с уверенностью сказать, что это ошибка в фреймворке.Поскольку он находится в аудиокоде, возможно, фреймворк не обрабатывает что-то, что получает от драйвера правильно.Трудно сказать наверняка.

Достаточно сказать, что AccessViolationException, выходящий из фреймворка, не является "нормальным".Это почти наверняка не ваша ошибка .

Функция IsEventRegistered, в которой возникает исключение, является unsafe функцией.Таким образом, вполне вероятно, что функция выполняет именно то, что говорит исключение: она обращается к недопустимому адресу памяти.

Исключение исходит из кода выключения для захвата звука (микрофон), поэтому вы делаете что-то с микрофономв вашем коде?Вы могли бы поэкспериментировать с использованием / не использованием микрофона и посмотреть, что произойдет.

Также: это происходит, когда вы запускаете без подключенного отладчика?(Ctrl + F5)

Что касается решения проблемы: Ваше решение не является плохим решением проблемы.

Если вы не можете позволить себе ждать три секунды, иВы хотите испачкать руки и написать очень сомнительный (полупортативный, не обязательно совместимый с) код: вы можете использовать отражение для доступа к частным свойствам аудиосистемы.Найдите список SoundEffectInstance объектов, которые создаются внутри себя при каждом вызове SoundEffect.Play, а затем остановите эти экземпляры перед тем, как завершить работу.

Или вы можете эффективно сделать то же самое, никогда не вызывая Play, новместо этого звоните CreateInstance и самостоятельно управляйте звуковыми эффектами "забей и забудь".Недостатком является то, что для этого нужно написать очень много кода!

1 голос
/ 24 февраля 2011

Можете ли вы заставить MyClass реализовать IDisposable и избавиться от SoundEffect в этом методе?

0 голосов
/ 22 января 2014

У меня была такая же проблема, и я делал нули для своих звуковых коллекций в классе finalizer (деструктор).У меня работает.

public class Audio
{
    private ContentManager content;
    public List<SoundEffectInstance> SoundInstance { get; private set; }
    public AudioEmitter Emitter { get; set; }
    public AudioListener Listener { get; set; }
    public List<SoundEffect> Sound { get; set; }
    public Audio(ContentManager content)
    {
        this.content = content;
        Emitter = new AudioEmitter();
        Listener = new AudioListener();
        Sound = new List<SoundEffect>();
        SoundInstance = new List<SoundEffectInstance>();
    }
    //set to null your sound instances and effects :D
    ~Audio()
    {
        Sound = null;
        SoundInstance = null;
    }
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...