2010-11-05 47 views
8

Tôi đang viết một ứng dụng viết cơ bản trong C# và tôi muốn có chương trình tạo âm thanh máy đánh chữ khi bạn nhập. Tôi đã kết nối sự kiện KeyPress trên RichTextBox của mình với chức năng sử dụng SoundPlayer để phát tệp wav ngắn mỗi lần nhấn phím, tuy nhiên tôi đã nhận thấy sau một thời gian máy tính của tôi chậm lại và kiểm tra quy trình của tôi, audiodlg .exe đang sử dụng 5 GIGABYTES RAM.SoundPlayer gây ra rò rỉ bộ nhớ?

Mã Tôi đang sử dụng như sau:

tôi khởi sự SoundPlayer như là một biến toàn cầu về chương trình bắt đầu với

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

Sau đó, trên sự kiện KeyPress tôi chỉ đơn giản gọi

sp.Play(); 

Có ai biết điều gì gây ra việc sử dụng bộ nhớ nặng? Tệp này dài hơn một giây, do đó, nó không nên làm tắc nghẽn điều quá nhiều.

+0

Nếu bạn nhận xét 'sp.Play();' bạn có thấy bộ nhớ của mình không còn tăng lên 5 Gb không? Nếu nó vẫn còn, có cái gì khác sai với mã của bạn. – JLWarlow

+0

Cập nhật trình điều khiển âm thanh của bạn. –

+0

Có, chắc chắn. Tôi chỉ định một chìa khóa để không làm gì cả, và một cái để phát tiếng ồn. Giữ phím "không làm gì" làm cho không có thay đổi để sử dụng bộ nhớ audiodg.exe của. Giữ phím "phát tiếng ồn" làm cho nó tăng đột biến nhanh chóng. Sau đó nó sẽ không rơi nếu tôi để nó trong vài phút. –

Trả lời

5

không sử dụng SoundPlayer - sử dụng waveOut... API thay vì:

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

SoundPlayer giống một món đồ chơi hơn là một sản phẩm thành phần sẵn sàng ion, mặc dù tôi chắc chắn rằng thực tập sinh MS đã viết nó có ý nghĩa tốt. :)

Cập nhật: nếu bạn sử dụng mẫu được liên kết và làm quen với mã, bạn sẽ thấy điều có thể sai với triển khai SoundPlayer. Phát âm thanh với các chức năng waveOut... bao gồm hai bộ đệm trong bộ nhớ: một bộ đệm nhỏ cho tiêu đề và một bộ đệm có khả năng lớn hơn chứa dữ liệu mẫu thực tế. Bài viết hotfix mà bạn đã liên kết đề cập đến sự rò rỉ vài trăm byte mỗi lần gọi là Play, có nghĩa là mã có thể khởi tạo tiêu đề mới mỗi lần và sau đó không xử lý nó đúng cách. (Đây là giả định SoundPlayer kết thúc tốt nhất API waveOut... - Tôi không biết đây có phải là trường hợp hay không)

Các lập trình viên được cho phép tối đa "không tái tạo lại bánh xe". Vâng, đôi khi bánh xe tuyệt vọng cần tái phát minh.

+0

Vào lúc 2014/09/17, liên kết bị hỏng. –

+1

Không thể tìm thấy mã nguồn ban đầu vì vậy tôi đã thêm một liên kết khác (có thể tốt hơn). – Sire

0

Thử sử dụng phương pháp Load của trình phát âm thanh để tải âm thanh và sau đó gọi phát. Phát sử dụng chuỗi thứ hai để tải (nếu chưa được tải) và phát tệp.

Có thể hàm khởi tạo không tải tệp ban đầu (điều tôi nghĩ là hoàn toàn có thể), nó kết hợp chặt chẽ trình phát với tên tệp âm thanh.

+0

Tôi vừa thử điều đó và bộ nhớ vẫn còn phát ra khi phát âm thanh. Tôi đang chạy Load() trên bộ khởi tạo của cửa sổ, vì vậy nó chắc chắn đang xảy ra. –

2

Nó có thể là một lỗi trong SoundPlayer.

Hãy thử bài viết này trên code project, có thể nó sẽ cung cấp cho bạn một số gợi ý.

+0

Tôi đã cố gắng thực hiện bài viết, cũng không hoạt động tôi sợ. –

0

Tôi đã thực hiện với this sample. WWFM (còn gọi là "Làm việc tốt cho tôi). Hãy thử tìm kiếm các lỗi trong mã của bạn (trong đó, tôi gần như chắc chắn, đủ tinh khiết) hoặc một tệp âm thanh khác.

+0

Vẫn phá vỡ cho tôi.Phải là một cái gì đó sai trái với máy tính của tôi. –

+0

Thử cập nhật trình điều khiển âm thanh của bạn, .NET và/hoặc cài đặt lại các cửa sổ (theo cách cực đoan nhất). Nên giúp đỡ =) – shybovycha

0

Hãy thử xử lý SoundPlayer sau khi phát âm thanh. .. Garbage Collector Nếu nó vẫn tiêu thụ bộ nhớ bổ sung, một cái gì đó thực sự khó chịu đang xảy ra và bạn nên chạy các bài kiểm tra trên máy tính khác

+0

Nó vẫn không làm việc cho tôi, tôi sẽ cố gắng thử nghiệm trên máy tính của tôi làm việc, xem nếu nó cũng làm điều đó. –

0

Tôi đã sử dụng chức năng PlaySound bên trong API Win32 trước để thực hiện điều gì đó tương tự. Mặc dù đây không phải là trong cùng một ngôn ngữ mà bạn đang sử dụng, dưới đây là một ví dụ về một chương trình mà sẽ đóng 'mahnamahna.wav' trên tất cả các tổ hợp phím 100. (Có, nó là khá buồn cười)

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 

trên sẽ không làm việc nếu không có sự dll (hook.dll) sau

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

này không nói đúng một câu trả lời, vì vậy tôi sẽ không khẳng định điều này là câu trả lời chấp nhận câu hỏi của tôi, nhưng nó là một giải pháp cho những người có cùng vấn đề (và cũng xác nhận rằng hệ thống của tôi không phải là lỗi)

Tôi quyết định triển khai âm thanh bằng thư viện AudioPlayback của ManagedDirectX, dễ sử dụng như SoundPlayer, nhưng đã giải quyết thành công vấn đề của tôi.

Đối với những người muốn biết, mã đơn giản:

1) Thêm tham chiếu đến dll phát lại âm thanh.

2) Tạo một đối tượng âm thanh (tôi đặt tên tôi âm thanh), làm cho nó một biến vào mẫu của bạn, do đó bạn có thể tham khảo nó một lần nữa, sử dụng các nhà xây dựng để thiết lập tên tập tin đó nên chơi

3) Chơi tập tin với sound.Play();

4) Nếu bạn cần để chơi các tập tin một lần nữa, sử dụng các dòng sau:

sound.SeekCurrentPosition(0, SeekPositionFlags.AbsolutePositioning); 

Đó là khá nhanh, và khá tốt. Sẽ có vấn đề về bộ nhớ nếu bạn cần nhiều hiệu ứng âm thanh khác nhau, bởi vì tất cả chúng sẽ liên tục trong bộ nhớ, nhưng nếu bạn cần một âm thanh để chơi nhiều, điều này sẽ làm điều đó mà không cần phải bỏ qua Audiodlg.exe

0

bạn nên cố gắng sử dụng()

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

khi quá trình kết thúc sp.Play() bộ nhớ trở về tự động hoá hệ thống của bạn.

+1

Hệ thống của tôi sử dụng nhiều bộ nhớ hơn thế nào? Tôi muốn tạo ra nó ngay từ đầu, sử dụng nó nhiều như tôi muốn và sau đó loại bỏ nó, thay vì tạo ra và phá hủy nó mỗi khi nó chạy (rất nhiều) –

+0

Xin lỗi tôi quên u cố gắng sử dụng âm thanh để gõ. – Hutchibang

Các vấn đề liên quan