You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用按钮终止DryWetMidi库的MIDI播放?

使用DryWetMidi实现MIDI播放终止功能

当前代码可播放指定路径的MIDI文件,但缺少终止播放的功能,且原代码中的SpinWait.SpinUntil会阻塞UI线程,导致停止按钮无法响应。以下是修正并添加停止功能的实现方案:

@using Melanchall.DryWetMidi.Multimedia;
@using Melanchall.DryWetMidi.Core;
@implements IDisposable

<span @onclick="@PlayMidi">
    <button>播放</button>
</span>
<span @onclick="@StopPlayback">
    <button disabled="@(!IsPlaying)">停止</button>
</span>

@code{
    private Playback _playback;
    private OutputDevice _outputDevice;
    private bool IsPlaying => _playback?.IsRunning ?? false;

    public async Task PlayMidi()
    {
        // 先终止正在进行的播放
        if (IsPlaying)
        {
            StopPlayback();
        }

        try
        {
            var midiFile = MidiFile.Read(MIDI.Path);
            _outputDevice = OutputDevice.GetByName("Microsoft GS Wavetable Synth");
            _playback = midiFile.GetPlayback(_outputDevice);
            
            // 订阅播放结束事件,自动清理资源
            _playback.Stopped += OnPlaybackStopped;
            
            // 异步启动播放,避免阻塞UI线程
            await Task.Run(() => _playback.Start());
        }
        catch (Exception ex)
        {
            Console.WriteLine($"播放出错: {ex.Message}");
            CleanupResources();
        }
    }

    public void StopPlayback()
    {
        if (_playback?.IsRunning == true)
        {
            _playback.Stop();
        }
        CleanupResources();
    }

    private void OnPlaybackStopped(object sender, EventArgs e)
    {
        CleanupResources();
        StateHasChanged(); // 更新UI按钮状态
    }

    private void CleanupResources()
    {
        _playback?.Dispose();
        _outputDevice?.Dispose();
        _playback = null;
        _outputDevice = null;
    }

    public void Dispose()
    {
        CleanupResources();
    }
}

关键修改说明:

  • 移除SpinWait.SpinUntil,改用Task.Run异步启动播放,避免阻塞UI线程,确保停止按钮能正常响应。
  • 添加StopPlayback方法,调用Playback.Stop()直接终止当前播放流程。
  • 新增IsPlaying属性,控制停止按钮的禁用状态,避免无效操作。
  • 订阅Playback.Stopped事件,无论播放正常结束还是被终止,都自动清理设备和播放资源。
  • 实现IDisposable接口,确保组件销毁时彻底释放资源,避免内存泄漏。
  • 添加异常捕获,处理播放过程中可能出现的路径错误、设备异常等问题。

内容的提问来源于stack exchange,提问作者Addlon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 05:40:27