[英]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.