Skip to content

Commit

Permalink
Fixed exception when unexpected disposed RtMidiCallback
Browse files Browse the repository at this point in the history
Keep reference to midi event callback in RtMidiIn interop to prevent GC bumbling off with the handler
  • Loading branch information
Daniel127 committed Sep 6, 2023
1 parent afc4adc commit e10a03d
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 8 deletions.
8 changes: 8 additions & 0 deletions RtMidi.Net/InteropServices/RtMidiIn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ namespace RtMidi.Net.InteropServices;
/// </summary>
internal class RtMidiIn : RtMidiBase
{
#pragma warning disable IDE0052
// ReSharper disable once NotAccessedField.Local
// Used to prevent garbage collection of the delegate
private RtMidiCallback? _midiCallback;
#pragma warning restore IDE0052

/// <summary>
/// Default constructor
/// </summary>
Expand Down Expand Up @@ -67,6 +73,7 @@ public override MidiApi GetCurrentApi()
/// passed to the callback function whenever it is called.</param>
public void SetCallback(RtMidiCallback callback, byte[]? userData)
{
_midiCallback = callback;
RtMidiInterop.rtmidi_in_set_callback(RtMidiPtr, callback, userData);
}

Expand Down Expand Up @@ -126,6 +133,7 @@ public void IgnoreTypes(bool midiSysex = true, bool midiTime = true, bool midiSe
/// <inheritdoc />
protected override void ReleaseUnmanagedResources()
{
_midiCallback = null;
RtMidiInterop.rtmidi_in_free(RtMidiPtr);
}
}
2 changes: 1 addition & 1 deletion WorkerTest/Program.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using WorkerTest;

IHost host = Host.CreateDefaultBuilder(args)
var host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
Expand Down
20 changes: 13 additions & 7 deletions WorkerTest/Worker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private MidiInputClient? _midiInputClient;
private const bool UseEventHandler = true; //Change to test

/// <summary>
/// Constructor
Expand All @@ -29,12 +30,14 @@ public override async Task StartAsync(CancellationToken cancellationToken)
}
if (devices.Any())
{
var devicePort = 1u; //TODO Change device to test
var devicePort = 1u; //Change device to test
var device = MidiManager.GetDeviceInfo(devicePort, MidiDeviceType.Input);
_midiInputClient = new MidiInputClient(device);
//TODO The event throws an exception after a while, i'm not sure why
//_midiInputClient.OnMessageReceived += MidiClient_OnMessageReceived;
//_midiInputClient.ActivateMessageReceivedEvent();
if (UseEventHandler)
{
_midiInputClient.OnMessageReceived += MidiClient_OnMessageReceived;
_midiInputClient.ActivateMessageReceivedEvent();
}
_midiInputClient.Open();
}
else
Expand All @@ -50,10 +53,13 @@ public override async Task StartAsync(CancellationToken cancellationToken)
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Executing");
while (!stoppingToken.IsCancellationRequested)
if (!UseEventHandler)
{
var (message, _) = await _midiInputClient!.GetMessageAsync(stoppingToken);
OnMessageReceived(message);
while (!stoppingToken.IsCancellationRequested)
{
var (message, _) = await _midiInputClient!.GetMessageAsync(stoppingToken);
OnMessageReceived(message);
}
}
}

Expand Down

0 comments on commit e10a03d

Please sign in to comment.