如何解决使用ATEM Mini SDK时出现的System.Runtime.InteropServices.COMException?
解决ATEM Mini SDK切换5次后触发COMException的问题
核心原因
ATEM Mini的SDK基于COM实现,.NET的垃圾回收机制不会自动清理COM对象的引用计数;再加上SDK默认限制最多5个并发连接实例,每次创建AtemSwitcher时都新建CBMDSwitcherDiscovery并发起连接,却没有释放旧的COM对象,导致5次后耗尽连接配额,抛出System.Runtime.InteropServices.COMException。
具体解决方案
- 复用Discovery实例:不要每次初始化都新建
CBMDSwitcherDiscovery,将其设为全局单例,因为Discovery仅负责设备发现和连接,无需重复创建。 - 手动释放COM资源:对于不再使用的
IBMDSwitcher、IBMDSwitcherMixEffectBlock等COM对象,必须调用Marshal.ReleaseComObject()手动释放,避免引用计数泄漏。 - 复用已有连接:不要每次切换都新建
AtemSwitcher实例,复用已建立的switcher连接直接执行切换操作即可。
修改后的代码示例
using System; using System.Linq; using System.Runtime.InteropServices; using BMDSwitcherAPI; public class AtemSwitcher : IDisposable { // 全局复用的Discovery单例 private static readonly IBMDSwitcherDiscovery _discovery = new CBMDSwitcherDiscovery(); private IBMDSwitcher _switcher; private IBMDSwitcherMixEffectBlock _me0; public AtemSwitcher() { // 仅在未连接或连接断开时重新建立连接 if (_switcher == null) { _discovery.ConnectTo("192.168.0.10", out _switcher, out _BMDSwitcherConnectToFailure _); _me0 = _switcher.MixEffectBlocks.Cast<IBMDSwitcherMixEffectBlock>().First(); } } // 执行视频输出切换 public void SwitchToProgramInput(uint inputId) { _me0.SetProgramInput(inputId); } // 手动释放COM资源 public void Dispose() { if (_me0 != null) { Marshal.ReleaseComObject(_me0); _me0 = null; } if (_switcher != null) { Marshal.ReleaseComObject(_switcher); _switcher = null; } // 程序退出时再释放Discovery(全局单例无需频繁释放) } }
额外注意事项
- 在Web应用中,建议将
AtemSwitcher注册为单例服务(比如ASP.NET Core的AddSingleton),避免重复创建连接。 - 应用停止或重启时,务必调用
Dispose()方法释放所有COM对象,防止残留无效连接占用配额。
内容的提问来源于stack exchange,提问作者Tomáš Mejzr
相关产品推荐
相关产品推荐

