SoundPlayer provoque-t-il des memory leaks?

J’écris une application d’écriture de base en C # et je voulais que le programme crée des sons de machine à écrire tels que vous les avez saisis. J’ai associé l’événement KeyPress de ma RichTextBox à une fonction qui utilise un SoundPlayer pour lire un court fichier wav chaque fois que vous appuyez sur une touche. Cependant, j’ai remarqué qu’après un certain temps mon ordinateur ralentissait et vérifiait mes processus, audiodlg .exe utilisait 5 GIGABYTES de RAM.

Le code que j’utilise est le suivant:

J’initialise SoundPlayer en tant que variable globale au début du programme

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

Ensuite, lors de l’événement KeyPress, j’appelle simplement

 sp.Play(); 

Est-ce que quelqu’un sait ce qui cause l’utilisation intensive de la mémoire? Le fichier dure moins d’une seconde, il ne devrait donc pas trop encrasser le contenu.

N’utilisez pas SoundPlayer – utilisez plutôt l’API waveOut... :

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

SoundPlayer ressemble plus à un jouet qu’à un composant prêt à la production, même si je suis sûr que le stagiaire MS qui l’a écrit a bien compris. 🙂

Mise à jour: si vous utilisez l’exemple lié et que vous vous familiarisez avec le code, vous verrez ce qui ne va probablement pas avec l’implémentation SoundPlayer . La lecture audio avec les fonctions waveOut... implique deux tampons en mémoire: un petit pour l’en-tête et un autre potentiellement plus grand que les données réelles. L’article de correctif que vous avez lié à la mention de la fuite de quelques centaines d’octets à chaque appel de Play , ce qui signifie que le code instancie probablement un nouvel en-tête à chaque fois et ne le supprime donc pas correctement. (Cela suppose que SoundPlayer enveloppe waveOut... API – Je ne sais pas si c’est le cas ou non)

Les programmeurs prennent pour acquis la maxime “ne réinventez pas la roue”. Parfois, la roue a désespérément besoin de réinventer.

Cela pourrait être un bug dans SoundPlayer.

Essayez cet article sur le projet de code , il vous donnera peut-être quelques indices.

Essayez d’utiliser la méthode Load du lecteur de son pour charger le son, puis appelez la lecture. Play utilise un second thread pour charger (s’il n’est pas déjà chargé) et lire le fichier.

Peut-être que le constructeur ne charge pas le fichier initialement (ce qui, à mon avis, est tout à fait possible), il associe le lecteur au nom du fichier son.

J’ai fini avec cet échantillon . WWFM (aka “a bien fonctionné pour moi). Essayez de chercher des erreurs dans votre code (qui, j’en suis presque sûr, est assez pur) – ou dans un autre fichier son.

Essayez de jeter SoundPlayer après avoir joué le son. Ensuite, lancez le ramasse-miettes. S’il utilise encore de la mémoire supplémentaire, il se passe quelque chose de vraiment désagréable et vous devez exécuter les tests sur un autre ordinateur.

J’ai déjà utilisé la fonction PlaySound dans l’API Win32 pour faire quelque chose de similaire. Bien que ceci ne soit pas dans la même langue que celle que vous utilisez, voici un exemple de programme qui va jouer “mahnamahna.wav” à chaque 100e frappe (oui, c’était assez amusant).

  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 ;Ssortingng 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 

Ce qui précède ne fonctionnera pas sans la dll suivante (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 

Ce n’est pas à proprement parler une réponse, donc je ne confirmerai pas cela comme étant la réponse acceptée à ma question, mais c’est une solution pour ceux qui ont eu les mêmes problèmes (et confirme également que ce n’est pas mon système qui est en défaut).

J’ai décidé d’implémenter le son à l’aide de la bibliothèque AudioPlayback de ManagedDirectX, aussi facile à utiliser que SoundPlayer, mais qui a résolu mon problème avec succès.

Pour ceux qui veulent savoir, le code est simple:

1) Ajoutez une référence à la DLL audioplayback.

2) Créez un object Audio (j’ai nommé mine sound), faites-en une variable de votre formulaire pour pouvoir vous y référer à nouveau, utilisez le constructeur pour définir le nom du fichier à lire.

3) Jouez le fichier avec sound.Play ();

4) Si vous avez besoin de rejouer le fichier, utilisez la ligne suivante:

 sound.SeekCurrentPosition(0, SeekPositionFlags.AbsolutePositioning); 

C’est assez rapide et assez bon. Il y aura des problèmes de mémoire si vous avez besoin de nombreux effets sonores différents, car ils seront tous constamment en mémoire, mais si vous avez besoin d’un son pour jouer beaucoup, celui-ci le fera sans gonfler votre Audiodlg.exe.

Vous devriez essayer d’utiliser ()

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

à la fin du processus, la mémoire de sp.Play () retourne à votre système automatique.