SoundPlayer вызывает утечки памяти? - PullRequest
9 голосов
/ 05 ноября 2010

Я пишу базовое приложение для письма на C #, и я хотел, чтобы программа издавала звуки пишущей машинки, когда вы печатали.Я подключил событие KeyPress на своем RichTextBox к функции, которая использует SoundPlayer для воспроизведения короткого файла wav при каждом нажатии клавиши, однако я заметил, что через некоторое время мой компьютер замедляет сканирование и проверяет свои процессы, audiodlg.exe использовал 5 ГБ ГБ.

Я использую следующий код:

Я запускаю SoundPlayer как глобальную переменную при запуске программы с

SoundPlayer sp = new SoundPlayer("typewriter.wav")

Затем в событии KeyPress я просто вызываю

sp.Play();

Кто-нибудь знает, что вызывает интенсивное использование памяти?Файл имеет длину менее секунды, поэтому он не должен слишком сильно засорять объект.

Ответы [ 8 ]

6 голосов
/ 29 января 2011

Не используйте SoundPlayer - используйте waveOut... API вместо:

http://www.codeproject.com/Articles/4889/A-full-duplex-audio-player-in-C-using-the-waveIn-w

SoundPlayer больше похож на игрушку, чем на готовый к производству компонент, хотя я уверен, что стажер MS, написавший это, имел в виду хорошо. :)

Обновление: Если вы используете связанный пример и познакомитесь с кодом, вы увидите, что, вероятно, не так с реализацией SoundPlayer. Воспроизведение аудио с помощью функций waveOut... включает два буфера в памяти: один маленький для заголовка и один потенциально большой буфер, который содержит фактические данные выборки. В статье исправлений, на которую вы ссылаетесь, упоминается утечка нескольких сотен байт каждый раз, когда вызывается Play, что означает, что код, вероятно, каждый раз создает новый заголовок, а затем не удаляет его должным образом. (Предполагается, что SoundPlayer обертывает API waveOut... - я не знаю, так ли это на самом деле)

Программисты считают само собой разумеющимся принцип "не изобретай велосипед". Ну, иногда колесо отчаянно нуждается в переосмыслении.

2 голосов
/ 05 ноября 2010

Это может быть ошибка в SoundPlayer.

Попробуйте эту статью на проекте кода , возможно, он даст вам некоторые подсказки.

0 голосов
/ 12 ноября 2011

Вы должны попробовать использовать ()

using(SoundPlayer sp = new SoundPlayer("typewriter.wav")) {
   sp.Play();
}

когда процесс завершает sp.Play () память возвращается к вашей системной автоматике.

0 голосов
/ 02 февраля 2011

Это не строго говоря ответ, поэтому я не буду подтверждать это как принятый ответ на мой вопрос, но это решение для тех, у кого были такие же проблемы (и также подтверждает, что это не моя система по вине )

Я решил реализовать звук с помощью библиотеки AudioPlayback ManagedDirectX, которая примерно так же проста в использовании, как SoundPlayer, но успешно решила мою проблему.

Для тех, кто хочет знать, код прост:

1) Добавить ссылку на аудиоплеер dll.

2) Создайте аудио объект (я назвал мой звук), сделайте его переменной в вашей форме, чтобы вы могли снова обратиться к нему, используйте конструктор, чтобы задать имя файла, который он должен воспроизводить

3) Воспроизвести файл со звуком. Play ();

4) Если вам нужно снова воспроизвести файл, используйте следующую строку:

sound.SeekCurrentPosition(0, SeekPositionFlags.AbsolutePositioning);

Это довольно быстро и довольно хорошо. Будут проблемы с памятью, если вам нужно много разных звуковых эффектов, потому что они все будут постоянно находиться в памяти, но если вам нужен один звук, чтобы играть много, этот будет делать это без всплывающей надписи Audiodlg.exe

0 голосов
/ 30 января 2011

Я использовал функцию PlaySound внутри Win32 API, чтобы сделать что-то подобное. Хотя это не тот язык, который вы используете, ниже приведен пример программы, которая будет воспроизводить «mahnamahna.wav» при каждом 100-м нажатии клавиши (да, это было довольно забавно)

 format PE GUI 4.0
entry start

;Mahna Mahna.

include 'win32a.inc'

include 'helper.asm'

section '.idata' import data readable writeable

    library kernel32,'KERNEL32.DLL',\
            user32,'USER32.DLL',\
            hook,'HOOK.DLL',\
            winmm,'WINMM.DLL'

    import  hook,\
            SetKeyPressedHandler,'SetKeyPressedHandler'

    import winmm,\
            PlaySound,'PlaySound'

    include 'api\kernel32.inc'
    include 'api\user32.inc'

section '.data' data readable writeable

    szWavFile db "mahnamahna.wav",0

    ;String saying what the dll is called.
    szDllName db "HOOK.DLL",0

    ;Name of the function in the dll for the keyboard procedure
    szf_KeyboardProc db "KeyboardProc",0

    ;handle to the dll
    hDll dd ?
    ;handle to the keyboard procedure
    hKeyboardProc dd ?
    ;handle to the hook
    hHook dd ?

    kInput KBINPUT

    keyCount dd 0x0 ;

    ;msg for the message pump
    msg MSG


section '.text' code readable executable

    start:

        ;Load the DLL into memory.
        invoke LoadLibraryA,szDllName
        cmp eax,0x0
        je exit
        mov [hDll],eax


        invoke GetProcAddress,[hDll],szf_KeyboardProc
        cmp eax,0x0
        je freeLibrary
        mov [hKeyboardProc],eax

        invoke SetKeyPressedHandler,KeyPressedHandler

    hook:
        invoke SetWindowsHookEx,WH_KEYBOARD_LL,[hKeyboardProc],[hDll],0x0
        cmp eax,0x0
        je freeLibrary
        mov [hHook],eax

    msg_loop:
        invoke  GetMessage,msg,NULL,0,0
        cmp eax,1
        jb  unhook
        jne msg_loop
        invoke  TranslateMessage,msg
        invoke  DispatchMessage,msg
    jmp msg_loop



    proc KeyPressedHandler code,wparam,lparam

        ;Move the VK Code of the key they pressed into al.
        xor eax,eax
        mov eax,[lparam]
        mov cx,word [eax]

        cmp [wparam],WM_KEYDOWN
        je .ProcessKeyDown
        cmp [wparam],WM_KEYUP
        je .ProcessKeyUp

        .ProcessKeyDown:

            ret ;No need to go any further - we only process characters on key up
        .ProcessKeyUp:
            mov edx,[keyCount]
            inc edx

            cmp cx,VK_F12
            je unhook

            ;Hotkeys.
            ;F12 - Quit.
            cmp edx,0x64
            jne .done
            call MahnaMahna
            xor edx,edx
            .done:
            mov [keyCount],edx
        ret
    endp

    proc MahnaMahna
        invoke PlaySound,szWavFile,0x0,0x20000
        ret
    endp

    unhook:
        invoke UnhookWindowsHookEx,[hHook]

    freeLibrary:
        invoke FreeLibrary,[hDll]
    exit: 
        invoke ExitProcess,0

Выше не будет работать без следующих DLL (hook.dll)

 format PE GUI 4.0 DLL
entry _DllMain

include 'win32a.inc'

section '.data' data readable writeable
    hKeyPressedHandler dd 0x0
section '.text' code readable executable

proc _DllMain hinstDLL,fdwReason,lpvReserved
    mov eax,TRUE
    ret
endp

    proc SetKeyPressedHandler hProc
        mov eax,[hProc]
        mov [hKeyPressedHandler],eax
        ret
    endp

    proc KeyboardProc code,wparam,lparam
        cmp [code],0x0
        jl CallNextHook

        cmp [hKeyPressedHandler],0x0;Make sure our event handler is set.
        je CallNextHook

        ;Call our handler.
        invoke hKeyPressedHandler,[code],[wparam],[lparam]

        CallNextHook:
            invoke CallNextHookEx,0x0,[code],[wparam],[lparam]
            ret
    endp

section '.idata' import data readable writeable

    library kernel32,'KERNEL32.DLL',\
            user32,'USER32.DLL'

    include 'api\kernel32.inc'
    include 'api\user32.inc'

section '.edata' export data readable
    export 'hook.DLL',\
        KeyboardProc,'KeyboardProc',\
        SetKeyPressedHandler,'SetKeyPressedHandler'

section '.reloc' fixups data discardable
0 голосов
/ 26 января 2011

Попробуйте утилизировать SoundPlayer после воспроизведения звука. Затем запустите сборщик мусора. Если он все еще потребляет дополнительную память, происходит нечто действительно неприятное, и вам следует запустить тесты на другом компьютере.

0 голосов
/ 25 января 2011

Я сделал с этот образец .WWFM (он же «работал хорошо для меня»). Попробуйте найти ошибки в своем коде (который, я почти уверен, достаточно чистый) или другом звуковом файле.

0 голосов
/ 05 ноября 2010

Попробуйте использовать метод звукового проигрывателя Load для загрузки звука, а затем вызовите воспроизведение. Воспроизведение использует второй поток для загрузки (если еще не загружен) и воспроизведения файла.

Возможно, конструктор не загружает файл изначально (что, я думаю, вполне возможно), он просто ассоциирует плеер с именем звукового файла.

...