簡體   English   中英

SoundPlayer導致內存泄漏?

[英]SoundPlayer causing Memory Leaks?

我正在用C#編寫一個基本的寫作應用程序,我希望程序能夠在輸入時輸出打字機聲音。 我已經將我的RichTextBox上的KeyPress事件掛鈎到一個函數,該函數使用SoundPlayer每次按下一個鍵時播放一個簡短的wav文件,但是我注意到一段時間后我的計算機慢慢爬行並檢查我的進程,audiodlg .exe正在使用5 GIGABYTES的RAM。

我正在使用的代碼如下:

我將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-using-the-waveIn-w

SoundPlayer是一個玩具,而不是一個可以生產的組件,雖然我確信編寫它的MS實習生意味着很好。 :)

更新:如果您使用鏈接的示例並熟悉代碼,您將看到SoundPlayer實現可能出現的SoundPlayer 使用waveOut...函數播放音頻涉及兩個內存緩沖區:一個小的用於標頭,一個可能大的緩沖區包含實際的樣本數據。 您鏈接的修補程序文章提到每次調用Play泄漏幾百個字節,這意味着代碼可能每次都實例化一個新的標頭,然后不正確地處理它。 (這是假設SoundPlayer包裝waveOut... API - 我不知道是否是這種情況)

程序員理所當然地認為“不要重新發明輪子”。 好吧,有時輪子迫切需要重新發明。

它可能是SoundPlayer中的一個錯誤。

試試這篇關於代碼項目的文章,也許會給你一些提示。

嘗試使用聲音播放器的Load方法加載聲音,然后調用play。 Play使用第二個線程加載(如果尚未加載)並播放該文件。

也許構造函數最初不加載文件(我認為這很可能),它會將播放器與聲音文件名相關聯。

我已經完成了這個樣本 WWFM(又稱“為我工作好”)。嘗試在代碼中搜索錯誤(我幾乎可以肯定,這是足夠純粹的)或其他聲音文件。

播放聲音后嘗試處理SoundPlayer。 然后運行垃圾收集器。 如果它仍然消耗額外的內存,一些非常討厭的東西正在發生,你應該在另一台計算機上運行測試。

我之前在Win32 API中使用過PlaySound函數來做類似的事情。 雖然這與您使用的語言不同,但下面是一個程序示例,它將在每100次擊鍵時播放“mahnamahna.wav”。(是的,這很有趣)

 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

這並不是嚴格意義上的答案,所以我不會將此確認為我的問題的可接受的答案,但對於那些遇到同樣問題的人來說這是一個解決方案(並且也確認這不是我的系統有問題)

我決定使用ManagedDirectX的AudioPlayback庫實現聲音,它與SoundPlayer一樣容易使用,但已成功解決了我的問題。

對於那些想要了解的人來說,代碼很簡單:

1)添加對audioplayback dll的引用。

2)創建一個Audio對象(我命名為我的聲音),使其成為表單上的變量,以便您可以再次引用它,使用構造函數設置它應該播放的文件名

3)用sound.Play()播放文件;

4)如果您需要再次播放該文件,請使用以下行:

sound.SeekCurrentPosition(0, SeekPositionFlags.AbsolutePositioning);

它相當快,而且相當不錯。 如果你需要很多不同的聲音效果會有內存問題,因為它們都會一直存在於內存中,但是如果你需要一個聲音來播放很多聲音,那么這個聲音就可以在沒有激活Audiodlg.exe的情況下實現。

你應該嘗試使用()

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

當進程完成sp.Play()內存返回到系統自動進程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM