CoreAudio OnVolumeNotification事件订阅导致资源管理器(explorer.exe)CPU使用率高

7

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

问题:功能上成功,但一旦订阅OnVolumeNotification,CPU倾向于占用30-50%的资源,具体取决于您的CPU性能。经过使用Process Explorer和Process Monitor的深入挖掘,发现explorer.exe和有时svchost.exe会被注册表读取调用所占用。我不确定是哪个注册表键。我认为我没有以有害的方式订阅此事件,因为我仔细管理订阅 - 它只被触发一次。

实施音量控制的逻辑流程

  1. 取消订阅端点OnVolumeNotification
  2. 设置端点音量标量属性(立即生效)
  3. 订阅端点OnVolumeNotification

Core Audio API涉及的基础win32方法是RegisterControlChangeNotifyUnregisterControlChangeNotify。问题可能是由这些方法或事件订阅的实现引起的吗?


1
为什么不清楚正在读取哪个注册表键?Process Monitor应该提供这些信息。可能会有帮助。另外,您尝试过调试explorer.exe吗? - Simon
@Simon,非常抱歉没有注意到你的评论。我没有找到任何特定的键,因为我对ProcMon不是很熟悉。我将发布一个解决方案来解决这个问题,以便那些可能遇到相同问题的人可以使用。 - erodewald
1个回答

0

不要:

  1. 取消订阅
  2. 更改音量/静音设置
  3. 重新订阅

我修改了我的逻辑,基本上使用带有后备字段的属性逻辑来管理何时更新。它并不完美,但非常接近,并且不会占用任何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;
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接