Вопрос

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

Код, который я использую следующим образом:

I инициализирую SoundPlayer в качестве глобальной переменной на запуске программы с

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

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

sp.Play();

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

Это было полезно?

Решение

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

http://www.codeproject.com/articles/4889/a-full-duplex-audio-player-in-c-ubsing-wavein-w.

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

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

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

Другие советы

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

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

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

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

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

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

Я использовал Playsound Функция внутри API Win32, прежде чем делать что-то подобное. Хотя это не на одном языке, который вы используете, ниже, приведен пример программы, которая будет играть в «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 (Cook.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

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

Я решил реализовать звук с использованием библиотеки аудиозаписи ManagedDirectx, которая так же простой в использовании в качестве SoundPlayer, но успешно решена моя проблема.

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

1) Добавить ссылку на DLL AudioPlayback.

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

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

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

sound.SeekCurrentPosition(0, SeekPositionFlags.AbsolutePositioning);

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

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

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

Когда процесс заканчивает SP.Play () Память возвращается в вашу системную автоматику.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top