CoreAudio OnVolumeNotification事件订阅导致explorer.exe中的CPU使用率过高

时间:2012-09-05 13:44:36

标签: c# .net wpf windows audio

背景:在Windows Vista及更高版本中,使用展开的Core Audio API(由Ray Molenkamp和Xavier Flix提供)通过订阅DefaultAudioEndpoint的OnVolumeNotification并在其设置音量时强制执行音量级别变化。

问题:功能上成功,但只要注册OnVolumeNotification,CPU就会根据CPU的功率固定在30-50%。经过Process Explorer&进程监视器显示,explorer.exe和有时svchost.exe将被注册表读取调用消耗。我不确定哪个注册表项。我不相信我以有害的方式订阅此活动,因为我仔细管理订阅 - 它只被解雇一次。

强制执行卷的逻辑流程

  1. 取消订阅端点OnVolumeNotification
  2. 设置端点卷标量属性(立即生效)
  3. 订阅端点OnVolumeNotification
  4. Core Audio API中涉及的基础win32方法是RegisterControlChangeNotifyUnregisterControlChangeNotify。问题是否可能是由这些或事件订阅的实施引起的?

1 个答案:

答案 0 :(得分:0)

而不是:

  1. 取消注册
  2. 更改音量/设定静音
  3. 重新订阅
  4. 我修改了我的逻辑,主要使用带有支持字段的属性中的逻辑来管理何时更新。它并不完美,但它非常接近并且它不占用任何CPU,它允许从滑块的外部输入完全支持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;
      }
    }