2010-11-05 14 views
8

Piszę podstawową aplikację do pisania w języku C# i chciałem, aby program generował dźwięki maszyny do pisania. Podłączyłem zdarzenie KeyPress w moim RichTextBox do funkcji, która używa SoundPlayera do odtwarzania krótkiego pliku WAV za każdym naciśnięciem klawisza, jednak zauważyłem, że po pewnym czasie mój komputer spowalnia przechodzenie i sprawdza moje procesy, audiodlg .exe używa 5 GIGABYTES RAM.SoundPlayer powoduje wycieki pamięci?

Kod używam jest następująco:

ja zainicjalizować SoundPlayer jako zmienna globalna na uruchomieniu programu z

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

Następnie na razie KeyPress ja po prostu zadzwonić

sp.Play(); 

Czy ktoś wie, co powoduje nadmierne zużycie pamięci? Plik ma mniej niż sekundę długości, więc nie powinien zbytnio zapychać tego przedmiotu.

+0

Jeśli skomentujesz 'sp.Play();' czy zauważysz, że twoja pamięć nie rośnie do 5 Gb? Jeśli nadal jest, jest coś jeszcze nie tak z twoim kodem. – JLWarlow

+0

Zaktualizuj sterowniki audio. –

+0

Tak, zdecydowanie. Przydzieliłem jeden klucz, żeby nic nie robić, i jeden, żeby grać hałas. Przytrzymanie klawisza "nie rób nic" nie zmienia użycia pamięci audiodg.exe. Przytrzymanie klawisza "hałas odtwarzania" powoduje gwałtowne skoki. Wtedy nie spada, jeśli zostawiam go na kilka minut. –

Odpowiedz

5

nie używaj SoundPlayer - użyj waveOut... API zamiast:

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

SoundPlayer jest bardziej jak zabawka niż produkt gotowy do jonów składnik, chociaż jestem pewien, że stażysta stwardnienia rozsianego, który napisał to znaczy dobrze. :)

Aktualizacja: jeśli używasz połączoną próbkę i zapoznać się z kodem, zobaczysz co chyba nie tak z realizacji SoundPlayer. Odtwarzanie dźwięku za pomocą funkcji waveOut... obejmuje dwa bufory w pamięci: jeden mały dla nagłówka i jeden potencjalnie duży bufor niż zawierający rzeczywiste przykładowe dane. Wspomniany artykuł z poprawką wspomina o przecieku kilkuset bajtów za każdym razem, gdy jest wywoływany Play, co oznacza, że ​​kod prawdopodobnie za każdym razem tworzy nowy nagłówek, a następnie nie należy go prawidłowo usuwać. (To zakłada, że ​​SoundPlayer zawija interfejs API waveOut... - nie wiem, czy tak jest, czy nie).

Programiści przyjmują za pewnik maksymę "nie odkrywaj ponownie koła". Cóż, czasami koło desperacko potrzebuje odnowienia.

+0

Na dzień 2014/09/17 link jest uszkodzony. –

+1

Nie można znaleźć oryginalnego kodu źródłowego, więc dodałem inny (prawdopodobnie lepszy) link. – Sire

0

Spróbuj użyć metody dźwięku odtwarzacza Load, aby załadować dźwięk, a następnie zadzwoń do gry. Play używa drugiego wątku do załadowania (jeśli nie jest już załadowany) i odtworzenia pliku.

Być może konstruktor nie wczytuje pliku początkowo (co moim zdaniem jest całkiem możliwe), to na pewno kojarzy odtwarzacz z nazwą pliku dźwiękowego.

+0

Właśnie próbowałem, a pamięć wciąż rośnie, gdy dźwięk jest odtwarzany. Używam Load() na inicjalizatorze mojego okna, więc na pewno się dzieje. –

2

Może to być błąd w SoundPlayer.

Spróbuj tego artykułu na temat code project, może to da ci kilka wskazówek.

+0

Próbowałem implementacji artykułu, który również nie działa Obawiam się. –

0

Zrobiłem z this sample. WWFM (inaczej "Worked Well For Me") Spróbuj wyszukać błędy w kodzie (co, jestem prawie pewien, jest wystarczająco czysty) lub inny plik dźwiękowy

+0

Nadal się dla mnie złamałam.To musi być coś nie tak z moim komputerem. –

+0

Spróbuj zaktualizować sterowniki dźwięku, .NET i/lub zainstalować ponownie okna (jako najbardziej ekstremalny sposób). Powinien pomóc =) – shybovycha

0

Spróbuj wyrzucić SoundPlayer po odtworzeniu dźwięku. .. Garbage Collector Jeśli nadal zużywa dodatkową pamięć, coś naprawdę paskudny się dzieje i trzeba uruchomić testy na innym komputerze

+0

To wciąż nie działa dla mnie, spróbuję przetestować na moim komputerze pracy, zobacz, czy to też robi. –

0

Użyłem funkcji PlaySound wewnątrz Win32 API, zanim zrobię coś podobnego. Chociaż nie jest to w tym samym języku, którego używasz, poniżej jest przykładem programu, który będzie „Play” mahnamahna.wav na każdym 100. naciśnięciem klawisza. (Tak, to było dość zabawne)

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 

powyższe nie będzie działać bez następującym 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

to nie jest ściśle mówiąc odpowiedzi, więc nie będę tego potwierdzić jako zaakceptowanej odpowiedzi na moje pytanie, ale jest to rozwiązanie dla tych, którzy mieli te same problemy (a także potwierdza, że ​​to nie mój system jest w błędzie)

Zdecydowałem się zaimplementować dźwięk za pomocą biblioteki AudioPlayback ManagedDirectX, która jest tak łatwa w użyciu jak SoundPlayer, ale z powodzeniem rozwiązała mój problem.

Dla tych, którzy chcą wiedzieć, kod jest prosty:

1) Dodaj odwołanie do biblioteki dll audioplayback.

2) Utwórz obiekt audio (Nazwałem mój dźwięk), sprawiają, że zmienna w formularzu, dzięki czemu można odnosić się do niego ponownie użyć konstruktora, aby ustawić nazwę pliku powinna ona odgrywać

3) Play the plik z dźwiękiem.Play();

4) Jeżeli trzeba ponownie odtworzyć plik, należy użyć następujący wiersz:

sound.SeekCurrentPosition(0, SeekPositionFlags.AbsolutePositioning); 

to dość szybko i dość dobre. Pojawią się problemy z pamięcią, jeśli potrzebujesz wielu różnych efektów dźwiękowych, ponieważ wszystkie one będą stale przechowywane w pamięci, ale jeśli potrzebujesz jednego dźwięku, aby zagrać dużo, to zrobi to bez balonia twojego Audiodlg.exe

0

należy spróbować użyć()

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

gdy proces wykończenie sp.Play() powrót pamięcią do automatyki systemu.

+1

Jak jednak mój system wykorzystuje więcej pamięci? Chcę go utworzyć na samym początku, użyć go tyle, ile chcę, a następnie usunąć, zamiast tworzyć i niszczać za każdym razem, gdy jest uruchamiany (co jest dużo). –

+0

Niestety, zapomniałem spróbować użyć dźwięku do pisania. – Hutchibang

Powiązane problemy