diff --git a/.github/workflows/ReleaseNotes.md b/.github/workflows/ReleaseNotes.md
index 883446ea..72eb8188 100644
--- a/.github/workflows/ReleaseNotes.md
+++ b/.github/workflows/ReleaseNotes.md
@@ -1,3 +1,4 @@
+* [Core] Fixed not working removal of event handlers from async events (#1479).
* [Client] Added support for passing the local endpoint (network card) which should be used (#1311).
* [Client] Exposed _PackageIdentifier_ in _MqttApplicationMessageReceivedEventArgs_ (thanks to @koepalex, #1466).
* [Server] Added a new event (_ClientAcknowledgedPublishPacketAsync_) which is fired whenever a client acknowledges a PUBLISH packet (QoS 1 and 2, #487).
diff --git a/MQTTnet.sln.DotSettings b/MQTTnet.sln.DotSettings
index 87d205d0..dfaffacc 100644
--- a/MQTTnet.sln.DotSettings
+++ b/MQTTnet.sln.DotSettings
@@ -226,9 +226,9 @@
</Entry>
</TypePattern>
</Patterns>
- // Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
+ Licensed to the .NET Foundation under one or more agreements.
+The .NET Foundation licenses this file to you under the MIT license.
+See the LICENSE file in the project root for more information.
True
True
True
diff --git a/Source/MQTTnet.Tests/Internal/AsyncEvent_Tests.cs b/Source/MQTTnet.Tests/Internal/AsyncEvent_Tests.cs
new file mode 100644
index 00000000..3c1fdc90
--- /dev/null
+++ b/Source/MQTTnet.Tests/Internal/AsyncEvent_Tests.cs
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using MQTTnet.Implementations;
+using MQTTnet.Internal;
+
+namespace MQTTnet.Tests.Internal
+{
+ [TestClass]
+ public sealed class AsyncEvent_Tests
+ {
+ int _testEventAsyncCount;
+
+ [TestMethod]
+ public async Task Attach_EventHandler()
+ {
+ var testClass = new TestClass();
+
+ testClass.TestEventAsync += OnTestEventAsync;
+
+ await testClass.FireEventAsync(EventArgs.Empty);
+
+ Assert.AreEqual(1, _testEventAsyncCount);
+ }
+
+ [TestMethod]
+ public async Task Detach_EventHandler()
+ {
+ var testClass = new TestClass();
+
+ testClass.TestEventAsync += OnTestEventAsync;
+ testClass.TestEventAsync -= OnTestEventAsync;
+
+ await testClass.FireEventAsync(EventArgs.Empty);
+
+ Assert.AreEqual(0, _testEventAsyncCount);
+ }
+
+ Task OnTestEventAsync(EventArgs arg)
+ {
+ Interlocked.Increment(ref _testEventAsyncCount);
+ return PlatformAbstractionLayer.CompletedTask;
+ }
+
+ sealed class TestClass
+ {
+ readonly AsyncEvent _testEvent = new AsyncEvent();
+
+ public event Func TestEventAsync
+ {
+ add => _testEvent.AddHandler(value);
+ remove => _testEvent.RemoveHandler(value);
+ }
+
+ public Task FireEventAsync(EventArgs eventArgs)
+ {
+ return _testEvent.InvokeAsync(eventArgs);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/MQTTnet/Internal/AsyncEventInvocator.cs b/Source/MQTTnet/Internal/AsyncEventInvocator.cs
index 55541837..6258b28b 100644
--- a/Source/MQTTnet/Internal/AsyncEventInvocator.cs
+++ b/Source/MQTTnet/Internal/AsyncEventInvocator.cs
@@ -21,12 +21,14 @@ namespace MQTTnet.Internal
public bool WrapsHandler(Action handler)
{
- return ReferenceEquals(_handler, handler);
+ // Do not use ReferenceEquals! It will not work with delegates.
+ return handler == _handler;
}
public bool WrapsHandler(Func handler)
{
- return ReferenceEquals(_asyncHandler, handler);
+ // Do not use ReferenceEquals! It will not work with delegates.
+ return handler == _asyncHandler;
}
public Task InvokeAsync(TEventArgs eventArgs)