2012-09-05 7 views
7

Tło: W systemie Windows Vista i nowszych, używając rozszerzonej Core Audio API (Ray Molenkamp i Xavier Flix) egzekwować poziom głośności poprzez zapisanie się na DefaultAudioEndpoint za OnVolumeNotification i ustawienie głośność po zmianie.CoreAudio OnVolumeNotification subskrypcji zdarzenie powoduje wysokie użycie procesora w explorer.exe

Problem: Funkcjonalnie sukces, ale jak tylko abonament OnVolumeNotification jest zarejestrowany, CPU ma tendencję, aby uzyskać sztywny kurs na 30-50% w zależności od mocy procesora. Po wielu kopaniu z Process Processerem & Process Monitor odkryto, że explorer.exe, a czasem svchost.exe, mogą zostać wykorzystane przez wywołania rejestru. Nie jestem pewien, który klucz rejestru. Nie wierzę, abym subskrybował to wydarzenie w sposób szkodliwy, ponieważ starannie zarządzam subskrypcją - jest on uruchamiany tylko raz.

przebieg procesu egzekwowania głośności

  1. Rezygnacja z końcowym OnVolumeNotification
  2. zestaw właściwości skalarne objętości końcowych (w trybie natychmiastowym)
  3. Zapisz do punktu końcowego OnVolumeNotification

Bazowego metody win32 zaangażowani w Core Audio API to RegisterControlChangeNotify i UnregisterControlChangeNotify. Czy to możliwe, że przyczyną problemu są te lub wdrożenie subskrypcji wydarzenia?

+1

Dlaczego nie jest jasne, który klucz rejestru jest czytany? Process Monitor powinien dostarczyć ci tych informacji. Może być pomocny. Czy próbowałeś też debugować explorer.exe? – Simon

+0

@Simon Przepraszam, że nie zauważyłem Twojego komentarza. Nie mogłem znaleźć żadnych konkretnych kluczy, nie jestem w 100% zaznajomiony z ProcMon. Mam zamiar rozwiązać ten problem dla tych, którzy mogą spotkać się z tym samym problemem. – erodewald

Odpowiedz

0

Zamiast:

  1. anulowanie subskrypcji
  2. Zmień wielkość/ustawić wyciszenie
  3. Ponowne Subskrybuj

zmodyfikowałem mój logiki zasadniczo używać logiki właściwościami pól podporowych zarządzać kiedy aktualizować. Nie jest idealny, ale jest cholernie blisko i nie pochłania żadnego procesora, a pozwala na zewnętrzne wejście z suwaka z pełną obsługą INPC.

public EndpointVolumeEnforcer() { 
    try { 
    mmDeviceEnumerator = new MMDeviceEnumerator(); 
    mmDevice = mmDeviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia); 
    audioEndpointVolume = mmDevice.AudioEndpointVolume; 
    audioEndpointVolume.OnVolumeNotification += data => { 
     VolumePercent = Convert.ToInt16(data.MasterVolume*100); 
     DeviceIsMuted = data.Muted; 
    }; 
    DesiredVolume = 65; 
    } 
    catch (Exception ex) { 
    // Logging logic here 
    } 
} 

public int DesiredVolume { 
    get { return _desiredVolume; } 
    private set { 
    if (_desiredVolume == value) return; 
    _desiredVolume = value; 
    NotifyOfPropertyChange(); 
    Enforce(_desiredVolume); 
    } 
} 

public int VolumePercent { 
    get { return volumePercent; } 
    private set { 
    if (volumePercent == value) return; 
    volumePercent = value; 
    if (volumePercent != _desiredVolume) { 
     volumePercent = _desiredVolume; 
     Enforce(volumePercent); 
    } 
    } 
} 

public void Enforce(int pct, bool mute = false) { 
    var adjusted = Convert.ToInt16(audioEndpointVolume.MasterVolumeLevelScalar*100); 
    if (adjusted != DesiredVolume) { 
    audioEndpointVolume.MasterVolumeLevelScalar = pct/100f; 
    } 
} 
Powiązane problemy