MVC中如何创建单例Model并复用ATEM Mini硬件连接?
问题:复用ATEM Mini连接的Model实例
我开发了一个连接ATEM Mini物理硬件的Model,搭配Controller和View实现控制功能。目前遇到的问题是:每次点击View中的按钮修改硬件参数时,都会重新创建Model实例并重新连接硬件。
补充说明:多次调用switcher.changeInput(switcher)后,硬件因重复连接开始拒绝请求,请问能否在View中复用已连接的单一Model实例?
Model代码
private IBMDSwitcher switcher; private IBMDSwitcherMixEffectBlock me0; public int camera { get; set; } public AtemSwitcher() { // 连接切换器 IBMDSwitcherDiscovery discovery = new CBMDSwitcherDiscovery(); discovery.ConnectTo("192.168.0.10", out IBMDSwitcher switcher, out _BMDSwitcherConnectToFailure failureReason); this.switcher = switcher; me0 = this.MixEffectBlocks.First(); } static long GetInputId(IBMDSwitcherInput input) { input.GetInputId(out long id); return id; } private static IBMDSwitcherInput getSwitcherInput(AtemSwitcher sw, int cam) { return sw.SwitcherInputs .Where((i, ret) => { i.GetPortType(out _BMDSwitcherPortType type); return type == _BMDSwitcherPortType.bmdSwitcherPortTypeExternal; }) .ElementAt(cam); } public void changeInput(AtemSwitcher sw) { me0.SetProgramInput(GetInputId(getSwitcherInput(sw, camera))); }
Controller代码
public IActionResult Atem() { AtemSwitcher sw = new AtemSwitcher(); return View("Connection", sw); } [HttpPost] public IActionResult Connection(AtemSwitcher switcher) { if (ModelState.IsValid) { i = 10; switcher.changeInput(switcher); } return View(); }
View代码
@model pokus222.Models.AtemSwitcher <h1>Atem control</h1> <div class="row"> <div class="col-md-4"> <form asp-action="Connection"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <div class="form-group"> <label asp-for="camera" class="control-label"></label> <br /> <input asp-for="camera" class="form-control" /> <span asp-validation-for="camera" class="text-danger"></span> </div> <div class="form-group"> <input type="submit" value="Přepni" class="btn btn-default" /> </div> </form> </div> </div>
解决方案
要复用单一Model实例,核心是避免每次请求都创建新的AtemSwitcher对象,可以通过以下方式实现:
1. 注册单例服务(ASP.NET Core)
将AtemSwitcher注册为单例,确保整个应用生命周期内只有一个实例:
- 在
Program.cs中添加注册代码:
builder.Services.AddSingleton<AtemSwitcher>();
- 修改Controller,通过构造函数注入获取实例:
private readonly AtemSwitcher _atemSwitcher; public YourControllerName(AtemSwitcher atemSwitcher) { _atemSwitcher = atemSwitcher; } public IActionResult Atem() { return View("Connection", _atemSwitcher); } [HttpPost] public IActionResult Connection(int camera) { if (ModelState.IsValid) { _atemSwitcher.camera = camera; _atemSwitcher.changeInput(_atemSwitcher); } return View(_atemSwitcher); }
2. 优化Model方法
changeInput方法无需传入自身实例,直接使用类内成员即可:
public void changeInput() { me0.SetProgramInput(GetInputId(getSwitcherInput(this, camera))); }
调用时改为_atemSwitcher.changeInput();
3. 增加连接异常处理
在Model构造函数中添加连接校验,避免启动失败:
public AtemSwitcher() { IBMDSwitcherDiscovery discovery = new CBMDSwitcherDiscovery(); var result = discovery.ConnectTo("192.168.0.10", out IBMDSwitcher switcher, out _BMDSwitcherConnectToFailure failureReason); if (result == 0 && switcher != null) { this.switcher = switcher; me0 = this.MixEffectBlocks.First(); } else { throw new Exception($"连接ATEM失败,原因:{failureReason}"); } }
4. 动态重连支持(可选)
添加重连方法,避免单例实例连接断开后无法恢复:
public bool Reconnect() { switcher?.Disconnect(); IBMDSwitcherDiscovery discovery = new CBMDSwitcherDiscovery(); var result = discovery.ConnectTo("192.168.0.10", out IBMDSwitcher newSwitcher, out _BMDSwitcherConnectToFailure failureReason); if (result == 0 && newSwitcher != null) { switcher = newSwitcher; me0 = this.MixEffectBlocks.First(); return true; } return false; }
内容的提问来源于stack exchange,提问作者Tomáš Mejzr
相关产品推荐
相关产品推荐

