From 53392ab1b204f61c92763e1b66ed7af75f29f0c8 Mon Sep 17 00:00:00 2001 From: Elad Zelingher Date: Wed, 23 Sep 2020 13:16:49 -0400 Subject: [PATCH 1/3] Calling AsyncDispose instead of Dispose so we don't call ActionBlock.Completion.Wait() --- .../Fleck/FleckWampConnection.cs | 4 +- .../RawSocketConnection.cs | 2 +- .../RawSocket/TcpClientConnection.cs | 2 +- .../VtortolaWampConnection.cs | 2 +- .../WebSockets/WebSocketWrapperConnection.cs | 4 +- .../AsyncConnection/AsyncWampConnection.cs | 15 +++-- .../Listener/Connections/IWampConnection.cs | 14 +++++ .../Connections/ReviveClientConnection.cs | 42 +++++++++++-- .../Core/Utilities/AsyncEventHandler.cs | 61 +++++++++++++++++++ 9 files changed, 130 insertions(+), 16 deletions(-) create mode 100644 src/netstandard/WampSharp/Core/Utilities/AsyncEventHandler.cs diff --git a/src/netstandard/Default/WampSharp.Fleck/Fleck/FleckWampConnection.cs b/src/netstandard/Default/WampSharp.Fleck/Fleck/FleckWampConnection.cs index 4079c4be4..9004613e3 100644 --- a/src/netstandard/Default/WampSharp.Fleck/Fleck/FleckWampConnection.cs +++ b/src/netstandard/Default/WampSharp.Fleck/Fleck/FleckWampConnection.cs @@ -45,9 +45,9 @@ private void OnConnectionError(Exception exception) RaiseConnectionError(exception); } - private void OnConnectionClose() + private async void OnConnectionClose() { - RaiseConnectionClosed(); + await RaiseConnectionClosed().ConfigureAwait(false); } protected override void Dispose() diff --git a/src/netstandard/Extensions/WampSharp.AspNetCore.RawSocket/RawSocketConnection.cs b/src/netstandard/Extensions/WampSharp.AspNetCore.RawSocket/RawSocketConnection.cs index 0c9952d41..89773d616 100644 --- a/src/netstandard/Extensions/WampSharp.AspNetCore.RawSocket/RawSocketConnection.cs +++ b/src/netstandard/Extensions/WampSharp.AspNetCore.RawSocket/RawSocketConnection.cs @@ -90,7 +90,7 @@ public async Task RunAsync() mIsConnected = false; } - RaiseConnectionClosed(); + await RaiseConnectionClosed().ConfigureAwait(false); } private void ProcessBuffer(in ReadOnlySequence buffer) diff --git a/src/netstandard/Extensions/WampSharp.RawSocket/RawSocket/TcpClientConnection.cs b/src/netstandard/Extensions/WampSharp.RawSocket/RawSocket/TcpClientConnection.cs index 623a48c60..1c53cdf08 100644 --- a/src/netstandard/Extensions/WampSharp.RawSocket/RawSocket/TcpClientConnection.cs +++ b/src/netstandard/Extensions/WampSharp.RawSocket/RawSocket/TcpClientConnection.cs @@ -111,7 +111,7 @@ await Stream } } - RaiseConnectionClosed(); + await RaiseConnectionClosed().ConfigureAwait(false); } catch (Exception ex) { diff --git a/src/netstandard/Extensions/WampSharp.Vtortola/VtortolaWampConnection.cs b/src/netstandard/Extensions/WampSharp.Vtortola/VtortolaWampConnection.cs index c5b85feca..a9071916b 100644 --- a/src/netstandard/Extensions/WampSharp.Vtortola/VtortolaWampConnection.cs +++ b/src/netstandard/Extensions/WampSharp.Vtortola/VtortolaWampConnection.cs @@ -49,7 +49,7 @@ await mWebsocket.ReadMessageAsync(CancellationToken.None) } } - RaiseConnectionClosed(); + await RaiseConnectionClosed().ConfigureAwait(false); } catch (Exception ex) { diff --git a/src/netstandard/Extensions/WampSharp.WebSockets/WebSockets/WebSocketWrapperConnection.cs b/src/netstandard/Extensions/WampSharp.WebSockets/WebSockets/WebSocketWrapperConnection.cs index e6bc3e8ef..b6a92ab2c 100644 --- a/src/netstandard/Extensions/WampSharp.WebSockets/WebSockets/WebSocketWrapperConnection.cs +++ b/src/netstandard/Extensions/WampSharp.WebSockets/WebSockets/WebSocketWrapperConnection.cs @@ -76,7 +76,7 @@ await this.ClientWebSocket.ConnectAsync(mAddressUri, mCancellationToken) catch (Exception ex) { RaiseConnectionError(ex); - RaiseConnectionClosed(); + await RaiseConnectionClosed().ConfigureAwait(false); } return false; @@ -134,7 +134,7 @@ data is very small. await CloseWebSocket().ConfigureAwait(false); } - RaiseConnectionClosed(); + await RaiseConnectionClosed().ConfigureAwait(false); } private async Task CloseWebSocket() diff --git a/src/netstandard/WampSharp/Core/Listener/Connections/AsyncConnection/AsyncWampConnection.cs b/src/netstandard/WampSharp/Core/Listener/Connections/AsyncConnection/AsyncWampConnection.cs index d7fd2684e..d91497d37 100644 --- a/src/netstandard/WampSharp/Core/Listener/Connections/AsyncConnection/AsyncWampConnection.cs +++ b/src/netstandard/WampSharp/Core/Listener/Connections/AsyncConnection/AsyncWampConnection.cs @@ -7,7 +7,7 @@ namespace WampSharp.Core.Listener { - public abstract class AsyncWampConnection : IWampConnection, + public abstract class AsyncWampConnection : IAsyncWampConnection, IAsyncDisposable { private readonly ActionBlock> mSendBlock; @@ -56,7 +56,14 @@ protected async Task InnerSend(WampMessage message) public event EventHandler ConnectionOpen; public event EventHandler> MessageArrived; - public event EventHandler ConnectionClosed; + public event AsyncEventHandler ConnectionClosedAsync; + + public event EventHandler ConnectionClosed + { + add => ConnectionClosedAsync += value.ConvertToAsync(); + remove => ConnectionClosedAsync -= value.ConvertToAsync(); + } + public event EventHandler ConnectionError; protected abstract Task SendAsync(WampMessage message); @@ -70,10 +77,10 @@ protected virtual void RaiseMessageArrived(WampMessage message) MessageArrived?.Invoke(this, new WampMessageArrivedEventArgs(message)); } - protected virtual void RaiseConnectionClosed() + protected virtual async Task RaiseConnectionClosed() { mLogger.Debug("Connection has been closed"); - ConnectionClosed?.Invoke(this, EventArgs.Empty); + await ConnectionClosedAsync?.InvokeAsync(this, EventArgs.Empty); } protected virtual void RaiseConnectionError(Exception ex) diff --git a/src/netstandard/WampSharp/Core/Listener/Connections/IWampConnection.cs b/src/netstandard/WampSharp/Core/Listener/Connections/IWampConnection.cs index bbceabd96..838d07f2b 100644 --- a/src/netstandard/WampSharp/Core/Listener/Connections/IWampConnection.cs +++ b/src/netstandard/WampSharp/Core/Listener/Connections/IWampConnection.cs @@ -48,4 +48,18 @@ public interface IWampConnection : IDisposable /// event EventHandler ConnectionError; } + + + /// + /// A with async features + /// + /// + internal interface IAsyncWampConnection : IWampConnection, + IAsyncDisposable + { + /// + /// Occurs when this connection closes. + /// + event AsyncEventHandler ConnectionClosedAsync; + } } \ No newline at end of file diff --git a/src/netstandard/WampSharp/Core/Listener/Connections/ReviveClientConnection.cs b/src/netstandard/WampSharp/Core/Listener/Connections/ReviveClientConnection.cs index ed1aaf848..a5d131f5a 100644 --- a/src/netstandard/WampSharp/Core/Listener/Connections/ReviveClientConnection.cs +++ b/src/netstandard/WampSharp/Core/Listener/Connections/ReviveClientConnection.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using WampSharp.Core.Message; namespace WampSharp.Core.Listener @@ -28,13 +29,28 @@ private IControlledWampConnection SetupConnection() IControlledWampConnection result = mFactory(); result.ConnectionOpen += OnConnectionOpen; - result.ConnectionClosed += OnConnectionClosed; result.ConnectionError += OnConnectionError; result.MessageArrived += OnMessageArrived; + if (result is IAsyncWampConnection asyncWampConnection) + { + asyncWampConnection.ConnectionClosedAsync += OnConnectionClosedAsync; + } + else + { + result.ConnectionClosed += OnConnectionClosed; + } + return result; } + private async Task OnConnectionClosedAsync(object sender, EventArgs e) + { + await DestroyConnectionAsync().ConfigureAwait(false); + + RaiseConnectionClosed(); + } + private void OnMessageArrived(object sender, WampMessageArrivedEventArgs e) { RaiseMessageArrived(e); @@ -52,17 +68,33 @@ private void OnConnectionClosed(object sender, EventArgs e) RaiseConnectionClosed(); } + private async Task DestroyConnectionAsync() + { + UnwireEvents(); + IAsyncWampConnection connection = mConnection as IAsyncWampConnection; + + connection.ConnectionClosedAsync -= OnConnectionClosedAsync; + await connection.DisposeAsync().ConfigureAwait(false); + + mConnection = null; + } + private void DestroyConnection() { - mConnection.ConnectionOpen -= OnConnectionOpen; - mConnection.ConnectionClosed -= OnConnectionClosed; - mConnection.ConnectionError -= OnConnectionError; - mConnection.MessageArrived -= OnMessageArrived; + UnwireEvents(); mConnection.Dispose(); mConnection = null; } + private void UnwireEvents() + { + mConnection.ConnectionOpen -= OnConnectionOpen; + mConnection.ConnectionError -= OnConnectionError; + mConnection.MessageArrived -= OnMessageArrived; + mConnection.ConnectionClosed -= OnConnectionClosed; + } + private void OnConnectionOpen(object sender, EventArgs e) { RaiseConnectionOpen(); diff --git a/src/netstandard/WampSharp/Core/Utilities/AsyncEventHandler.cs b/src/netstandard/WampSharp/Core/Utilities/AsyncEventHandler.cs new file mode 100644 index 000000000..0a50bc6f4 --- /dev/null +++ b/src/netstandard/WampSharp/Core/Utilities/AsyncEventHandler.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; + +namespace WampSharp.Core +{ + public delegate Task AsyncEventHandler(object sender, TEventArgs e) where TEventArgs : EventArgs; + + public static class AsyncEventHandlerExtensions + { + public static async Task InvokeAsync(this AsyncEventHandler handler, object sender, + TEventArgs e) where TEventArgs : EventArgs + { + if (handler == null) + { + throw new ArgumentNullException(nameof(handler)); + } + + Delegate[] invocationList = handler.GetInvocationList(); + + foreach (AsyncEventHandler currentSubscriber in invocationList + .Cast>()) + { + await currentSubscriber(sender, e).ConfigureAwait(false); + } + } + + public static AsyncEventHandler ConvertToAsync + (this EventHandler handler) + { + if (handler == null) + { + throw new ArgumentNullException(nameof(handler)); + } + + return (sender, args) => + { + handler(sender, args); + return Task.CompletedTask; + }; + } + + + public static AsyncEventHandler ConvertToAsync + (this EventHandler handler) where TEventArgs : EventArgs + { + if (handler == null) + { + throw new ArgumentNullException(nameof(handler)); + } + + return (sender, args) => + { + handler(sender, args); + return Task.CompletedTask; + }; + } + } +} \ No newline at end of file From 719ae23c8d42c4c6a1c8c4f31650284426bbd7e9 Mon Sep 17 00:00:00 2001 From: Elad Zelingher Date: Wed, 23 Sep 2020 15:50:40 -0400 Subject: [PATCH 2/3] Adding NuGet package for blazor-changes --- .github/workflows/githubPackages.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/githubPackages.yml b/.github/workflows/githubPackages.yml index fbdeb0453..7f34bdcda 100644 --- a/.github/workflows/githubPackages.yml +++ b/.github/workflows/githubPackages.yml @@ -1,9 +1,9 @@ -name: GitHub packages NuGet generation +name: GitHub packages Blazor NuGet generation on: push: branches: - - master + - blazor-changes jobs: build: @@ -11,12 +11,12 @@ jobs: name: Update NuGet steps: - name: Checkout repository - uses: actions/checkout@master + uses: actions/checkout@blazor-changes - name: Build solution and generate NuGet package run: | cd src\netstandard\ - dotnet pack -c Release -o out /p:Version="${{ secrets.PACKAGE_VERSION }}-develop-${{ github.run_number }}" + dotnet pack -c Release -o out /p:Version="${{ secrets.PACKAGE_VERSION }}-blazor-${{ github.run_number }}" - name: Install NuGet client uses: warrenbuckley/Setup-Nuget@v1 From ec578b4645f8213fc8535fed3d9946b7708f59a3 Mon Sep 17 00:00:00 2001 From: Elad Zelingher Date: Wed, 23 Sep 2020 15:55:06 -0400 Subject: [PATCH 3/3] Update githubPackages.yml --- .github/workflows/githubPackages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/githubPackages.yml b/.github/workflows/githubPackages.yml index 7f34bdcda..0f3837f00 100644 --- a/.github/workflows/githubPackages.yml +++ b/.github/workflows/githubPackages.yml @@ -11,7 +11,7 @@ jobs: name: Update NuGet steps: - name: Checkout repository - uses: actions/checkout@blazor-changes + uses: actions/checkout@master - name: Build solution and generate NuGet package run: |