diff --git a/src/SignalR/clients/csharp/Client.Core/ref/Microsoft.AspNetCore.SignalR.Client.Core.csproj b/src/SignalR/clients/csharp/Client.Core/ref/Microsoft.AspNetCore.SignalR.Client.Core.csproj index fbfef8ba997b..a3f841dd7f5b 100644 --- a/src/SignalR/clients/csharp/Client.Core/ref/Microsoft.AspNetCore.SignalR.Client.Core.csproj +++ b/src/SignalR/clients/csharp/Client.Core/ref/Microsoft.AspNetCore.SignalR.Client.Core.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + netstandard2.0;netcoreapp3.0 @@ -11,4 +11,12 @@ + + + + + + + + diff --git a/src/SignalR/clients/csharp/Client.Core/ref/Microsoft.AspNetCore.SignalR.Client.Core.netcoreapp3.0.cs b/src/SignalR/clients/csharp/Client.Core/ref/Microsoft.AspNetCore.SignalR.Client.Core.netcoreapp3.0.cs new file mode 100644 index 000000000000..facbb2b77379 --- /dev/null +++ b/src/SignalR/clients/csharp/Client.Core/ref/Microsoft.AspNetCore.SignalR.Client.Core.netcoreapp3.0.cs @@ -0,0 +1,165 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.AspNetCore.Internal +{ + public static partial class AwaitableThreadPool + { + public static Microsoft.AspNetCore.Internal.AwaitableThreadPool.Awaitable Yield() { throw null; } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Size=1)] + public readonly partial struct Awaitable : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion + { + public bool IsCompleted { get { throw null; } } + public Microsoft.AspNetCore.Internal.AwaitableThreadPool.Awaitable GetAwaiter() { throw null; } + public void GetResult() { } + public void OnCompleted(System.Action continuation) { } + public void UnsafeOnCompleted(System.Action continuation) { } + } + } +} +namespace Microsoft.AspNetCore.SignalR.Client +{ + public partial class HubConnection + { + public static readonly System.TimeSpan DefaultHandshakeTimeout; + public static readonly System.TimeSpan DefaultKeepAliveInterval; + public static readonly System.TimeSpan DefaultServerTimeout; + public HubConnection(Microsoft.AspNetCore.SignalR.Client.IConnectionFactory connectionFactory, Microsoft.AspNetCore.SignalR.Protocol.IHubProtocol protocol, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { } + public HubConnection(Microsoft.AspNetCore.SignalR.Client.IConnectionFactory connectionFactory, Microsoft.AspNetCore.SignalR.Protocol.IHubProtocol protocol, System.IServiceProvider serviceProvider, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { } + public string ConnectionId { get { throw null; } } + public System.TimeSpan HandshakeTimeout { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public System.TimeSpan KeepAliveInterval { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public System.TimeSpan ServerTimeout { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public Microsoft.AspNetCore.SignalR.Client.HubConnectionState State { get { throw null; } } + public event System.Func Closed { add { } remove { } } + [System.Diagnostics.DebuggerStepThroughAttribute] + public System.Threading.Tasks.Task DisposeAsync() { throw null; } + [System.Diagnostics.DebuggerStepThroughAttribute] + public System.Threading.Tasks.Task InvokeCoreAsync(string methodName, System.Type returnType, object[] args, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public System.IDisposable On(string methodName, System.Type[] parameterTypes, System.Func handler, object state) { throw null; } + public void Remove(string methodName) { } + [System.Diagnostics.DebuggerStepThroughAttribute] + public System.Threading.Tasks.Task SendCoreAsync(string methodName, object[] args, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + [System.Diagnostics.DebuggerStepThroughAttribute] + public System.Threading.Tasks.Task StartAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + [System.Diagnostics.DebuggerStepThroughAttribute] + public System.Threading.Tasks.Task StopAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + [System.Diagnostics.DebuggerStepThroughAttribute] + public System.Threading.Tasks.Task> StreamAsChannelCoreAsync(string methodName, System.Type returnType, object[] args, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public System.Collections.Generic.IAsyncEnumerable StreamAsyncCore(string methodName, object[] args, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + } + public partial class HubConnectionBuilder : Microsoft.AspNetCore.SignalR.Client.IHubConnectionBuilder, Microsoft.AspNetCore.SignalR.ISignalRBuilder + { + public HubConnectionBuilder() { } + public Microsoft.Extensions.DependencyInjection.IServiceCollection Services { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public Microsoft.AspNetCore.SignalR.Client.HubConnection Build() { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals(object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public new System.Type GetType() { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override string ToString() { throw null; } + } + public static partial class HubConnectionBuilderExtensions + { + public static Microsoft.AspNetCore.SignalR.Client.IHubConnectionBuilder ConfigureLogging(this Microsoft.AspNetCore.SignalR.Client.IHubConnectionBuilder hubConnectionBuilder, System.Action configureLogging) { throw null; } + } + public static partial class HubConnectionExtensions + { + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, object arg10, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, object arg10, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task InvokeCoreAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object[] args, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + [System.Diagnostics.DebuggerStepThroughAttribute] + public static System.Threading.Tasks.Task InvokeCoreAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object[] args, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Action handler) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Func handler) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Type[] parameterTypes, System.Func handler) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Action handler) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Func handler) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Action handler) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Func handler) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Action handler) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Func handler) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Action handler) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Func handler) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Action handler) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Func handler) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Action handler) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Func handler) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Action handler) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Func handler) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Action handler) { throw null; } + public static System.IDisposable On(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Func handler) { throw null; } + public static System.Threading.Tasks.Task SendAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, object arg10, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task SendAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task SendAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task SendAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task SendAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task SendAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task SendAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task SendAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task SendAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task SendAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task SendAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task> StreamAsChannelAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, object arg10, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task> StreamAsChannelAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task> StreamAsChannelAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task> StreamAsChannelAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task> StreamAsChannelAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task> StreamAsChannelAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task> StreamAsChannelAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task> StreamAsChannelAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task> StreamAsChannelAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task> StreamAsChannelAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.Task> StreamAsChannelAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + [System.Diagnostics.DebuggerStepThroughAttribute] + public static System.Threading.Tasks.Task> StreamAsChannelCoreAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object[] args, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Collections.Generic.IAsyncEnumerable StreamAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, object arg10, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Collections.Generic.IAsyncEnumerable StreamAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Collections.Generic.IAsyncEnumerable StreamAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Collections.Generic.IAsyncEnumerable StreamAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Collections.Generic.IAsyncEnumerable StreamAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Collections.Generic.IAsyncEnumerable StreamAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Collections.Generic.IAsyncEnumerable StreamAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Collections.Generic.IAsyncEnumerable StreamAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Collections.Generic.IAsyncEnumerable StreamAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, object arg2, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Collections.Generic.IAsyncEnumerable StreamAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, object arg1, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Collections.Generic.IAsyncEnumerable StreamAsync(this Microsoft.AspNetCore.SignalR.Client.HubConnection hubConnection, string methodName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + } + public enum HubConnectionState + { + Connected = 1, + Disconnected = 0, + } + public partial interface IConnectionFactory + { + System.Threading.Tasks.Task ConnectAsync(Microsoft.AspNetCore.Connections.TransferFormat transferFormat, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + System.Threading.Tasks.Task DisposeAsync(Microsoft.AspNetCore.Connections.ConnectionContext connection); + } + public partial interface IHubConnectionBuilder : Microsoft.AspNetCore.SignalR.ISignalRBuilder + { + Microsoft.AspNetCore.SignalR.Client.HubConnection Build(); + } +} diff --git a/src/SignalR/clients/csharp/Client.Core/src/HubConnection.cs b/src/SignalR/clients/csharp/Client.Core/src/HubConnection.cs index 7807107d779b..e31501cf7ad1 100644 --- a/src/SignalR/clients/csharp/Client.Core/src/HubConnection.cs +++ b/src/SignalR/clients/csharp/Client.Core/src/HubConnection.cs @@ -17,6 +17,7 @@ using Microsoft.AspNetCore.Connections.Features; using Microsoft.AspNetCore.Internal; using Microsoft.AspNetCore.SignalR.Client.Internal; +using Microsoft.AspNetCore.SignalR.Internal; using Microsoft.AspNetCore.SignalR.Protocol; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -436,6 +437,46 @@ private async Task StopAsyncCore(bool disposing) } } +#if NETCOREAPP3_0 + + /// + /// Invokes a streaming hub method on the server using the specified method name, return type and arguments. + /// + /// The return type of the streaming server method. + /// The name of the server method to invoke. + /// The arguments used to invoke the server method. + /// The token to monitor for cancellation requests. The default value is . + /// + /// A that represents the stream. + /// + public IAsyncEnumerable StreamAsyncCore(string methodName, object[] args, CancellationToken cancellationToken = default) + { + var cts = cancellationToken.CanBeCanceled ? CancellationTokenSource.CreateLinkedTokenSource(cancellationToken) : new CancellationTokenSource(); + var stream = CastIAsyncEnumerable(methodName, args, cts); + var cancelableStream = AsyncEnumerableAdapters.MakeCancelableTypedAsyncEnumerable(stream, cts); + return cancelableStream; + } + + private async IAsyncEnumerable CastIAsyncEnumerable(string methodName, object[] args, CancellationTokenSource cts) + { + var reader = await StreamAsChannelCoreAsync(methodName, typeof(T), args, cts.Token); + try + { + while (await reader.WaitToReadAsync(cts.Token)) + { + while (reader.TryRead(out var item)) + { + yield return (T)item; + } + } + } + finally + { + cts.Dispose(); + } + } +#endif + private async Task> StreamAsChannelCoreAsyncCore(string methodName, Type returnType, object[] args, CancellationToken cancellationToken) { async Task OnStreamCanceled(InvocationRequest irq) diff --git a/src/SignalR/clients/csharp/Client.Core/src/HubConnectionExtensions.StreamAsync.cs b/src/SignalR/clients/csharp/Client.Core/src/HubConnectionExtensions.StreamAsync.cs new file mode 100644 index 000000000000..a30a6d6136fe --- /dev/null +++ b/src/SignalR/clients/csharp/Client.Core/src/HubConnectionExtensions.StreamAsync.cs @@ -0,0 +1,242 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Threading; +using System.Threading.Tasks; +using System.Threading.Channels; +using System.Collections.Generic; + +namespace Microsoft.AspNetCore.SignalR.Client +{ + /// + /// Extension methods for . + /// + public static partial class HubConnectionExtensions + { + +#if NETCOREAPP3_0 + + /// + /// Invokes a streaming hub method on the server using the specified method name and return type. + /// + /// The return type of the streaming server method. + /// The hub connection. + /// The name of the server method to invoke. + /// The token to monitor for cancellation requests. The default value is . + /// + /// A that represents the stream. + /// + public static IAsyncEnumerable StreamAsync(this HubConnection hubConnection, string methodName, CancellationToken cancellationToken = default) + { + return hubConnection.StreamAsyncCore(methodName, Array.Empty(), cancellationToken); + } + + /// + /// Invokes a streaming hub method on the server using the specified method name, return type and argument. + /// + /// The return type of the streaming server method. + /// The hub connection. + /// The name of the server method to invoke. + /// The first argument. + /// The token to monitor for cancellation requests. The default value is . + /// + /// A that represents the stream. + /// + public static IAsyncEnumerable StreamAsync(this HubConnection hubConnection, string methodName, object arg1, CancellationToken cancellationToken = default) + { + return hubConnection.StreamAsyncCore(methodName, new[] { arg1 }, cancellationToken); + } + + /// + /// Invokes a streaming hub method on the server using the specified method name, return type and argument. + /// + /// The return type of the streaming server method. + /// The hub connection. + /// The name of the server method to invoke. + /// The first argument. + /// The second argument. + /// The token to monitor for cancellation requests. The default value is . + /// + /// A that represents the stream. + /// + public static IAsyncEnumerable StreamAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, CancellationToken cancellationToken = default) + { + return hubConnection.StreamAsyncCore(methodName, new[] { arg1, arg2 }, cancellationToken); + } + + /// + /// Invokes a streaming hub method on the server using the specified method name, return type and argument. + /// + /// The return type of the streaming server method. + /// The hub connection. + /// The name of the server method to invoke. + /// The first argument. + /// The second argument. + /// The third argument. + /// The token to monitor for cancellation requests. The default value is . + /// + /// A that represents the stream. + /// + public static IAsyncEnumerable StreamAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, CancellationToken cancellationToken = default) + { + return hubConnection.StreamAsyncCore(methodName, new[] { arg1, arg2, arg3 }, cancellationToken); + } + + /// + /// Invokes a streaming hub method on the server using the specified method name, return type and argument. + /// + /// The return type of the streaming server method. + /// The hub connection. + /// The name of the server method to invoke. + /// The first argument. + /// The second argument. + /// The third argument. + /// The fourth argument. + /// The token to monitor for cancellation requests. The default value is . + /// + /// A that represents the stream. + /// + public static IAsyncEnumerable StreamAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, CancellationToken cancellationToken = default) + { + return hubConnection.StreamAsyncCore(methodName, new[] { arg1, arg2, arg3, arg4 }, cancellationToken); + } + + /// + /// Invokes a streaming hub method on the server using the specified method name, return type and argument. + /// + /// The return type of the streaming server method. + /// The hub connection. + /// The name of the server method to invoke. + /// The first argument. + /// The second argument. + /// The third argument. + /// The fourth argument. + /// The fifth argument. + /// The token to monitor for cancellation requests. The default value is . + /// + /// A that represents the stream. + /// + public static IAsyncEnumerable StreamAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, CancellationToken cancellationToken = default) + { + return hubConnection.StreamAsyncCore(methodName, new[] { arg1, arg2, arg3, arg4, arg5 }, cancellationToken); + } + + /// + /// Invokes a streaming hub method on the server using the specified method name, return type and argument. + /// + /// The return type of the streaming server method. + /// The hub connection. + /// The name of the server method to invoke. + /// The first argument. + /// The second argument. + /// The third argument. + /// The fourth argument. + /// The fifth argument. + /// The sixth argument. + /// The token to monitor for cancellation requests. The default value is . + /// + /// A that represents the stream. + /// + public static IAsyncEnumerable StreamAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, CancellationToken cancellationToken = default) + { + return hubConnection.StreamAsyncCore(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6 }, cancellationToken); + } + + /// + /// Invokes a streaming hub method on the server using the specified method name, return type and argument. + /// + /// The return type of the streaming server method. + /// The hub connection. + /// The name of the server method to invoke. + /// The first argument. + /// The second argument. + /// The third argument. + /// The fourth argument. + /// The fifth argument. + /// The sixth argument. + /// The seventh argument. + /// The token to monitor for cancellation requests. The default value is . + /// + /// A that represents the stream. + /// + public static IAsyncEnumerable StreamAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, CancellationToken cancellationToken = default) + { + return hubConnection.StreamAsyncCore(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7 }, cancellationToken); + } + + /// + /// Invokes a streaming hub method on the server using the specified method name, return type and argument. + /// + /// The return type of the streaming server method. + /// The hub connection. + /// The name of the server method to invoke. + /// The first argument. + /// The second argument. + /// The third argument. + /// The fourth argument. + /// The fifth argument. + /// The sixth argument. + /// The seventh argument. + /// The eighth argument. + /// The token to monitor for cancellation requests. The default value is . + /// + /// A that represents the stream. + /// + public static IAsyncEnumerable StreamAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, CancellationToken cancellationToken = default) + { + return hubConnection.StreamAsyncCore(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 }, cancellationToken); + } + + /// + /// Invokes a streaming hub method on the server using the specified method name, return type and argument. + /// + /// The return type of the streaming server method. + /// The hub connection. + /// The name of the server method to invoke. + /// The first argument. + /// The second argument. + /// The third argument. + /// The fourth argument. + /// The fifth argument. + /// The sixth argument. + /// The seventh argument. + /// The eighth argument. + /// The ninth argument. + /// The token to monitor for cancellation requests. The default value is . + /// + /// A that represents the stream. + /// + public static IAsyncEnumerable StreamAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, CancellationToken cancellationToken = default) + { + return hubConnection.StreamAsyncCore(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 }, cancellationToken); + } + + /// + /// Invokes a streaming hub method on the server using the specified method name, return type and argument. + /// + /// The return type of the streaming server method. + /// The hub connection. + /// The name of the server method to invoke. + /// The first argument. + /// The second argument. + /// The third argument. + /// The fourth argument. + /// The fifth argument. + /// The sixth argument. + /// The seventh argument. + /// The eighth argument. + /// The ninth argument. + /// The tenth argument. + /// The token to monitor for cancellation requests. The default value is . + /// + /// A that represents the stream. + /// + public static IAsyncEnumerable StreamAsync(this HubConnection hubConnection, string methodName, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, object arg10, CancellationToken cancellationToken = default) + { + return hubConnection.StreamAsyncCore(methodName, new[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 }, cancellationToken); + } +#endif + + } +} diff --git a/src/SignalR/clients/csharp/Client.Core/src/Microsoft.AspNetCore.SignalR.Client.Core.csproj b/src/SignalR/clients/csharp/Client.Core/src/Microsoft.AspNetCore.SignalR.Client.Core.csproj index dbd15acce9df..92b57f357d74 100644 --- a/src/SignalR/clients/csharp/Client.Core/src/Microsoft.AspNetCore.SignalR.Client.Core.csproj +++ b/src/SignalR/clients/csharp/Client.Core/src/Microsoft.AspNetCore.SignalR.Client.Core.csproj @@ -1,8 +1,8 @@ - + Client for ASP.NET Core SignalR - netstandard2.0 + netstandard2.0;netcoreapp3.0 Microsoft.AspNetCore.SignalR.Client true @@ -13,6 +13,7 @@ + diff --git a/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs b/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs index 9ffe7b3eb99e..0858941210d1 100644 --- a/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs +++ b/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs @@ -322,6 +322,203 @@ public async Task CanInvokeFromOnHandler(string protocolName, HttpTransportType } } + [Theory] + [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))] + [LogLevel(LogLevel.Trace)] + public async Task StreamAsyncCoreTest(string protocolName, HttpTransportType transportType, string path) + { + var protocol = HubProtocols[protocolName]; + using (StartServer(out var server)) + { + var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); + try + { + await connection.StartAsync().OrTimeout(); + var expectedValue = 0; + var streamTo = 5; + var asyncEnumerable = connection.StreamAsyncCore("Stream", new object[] { streamTo }); + await foreach (var streamValue in asyncEnumerable) + { + Assert.Equal(expectedValue, streamValue); + expectedValue++; + } + + Assert.Equal(streamTo, expectedValue); + } + catch (Exception ex) + { + LoggerFactory.CreateLogger().LogError(ex, "{ExceptionType} from test", ex.GetType().FullName); + throw; + } + finally + { + await connection.DisposeAsync().OrTimeout(); + } + } + } + + [Theory] + [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))] + [LogLevel(LogLevel.Trace)] + public async Task StreamAsyncTest(string protocolName, HttpTransportType transportType, string path) + { + var protocol = HubProtocols[protocolName]; + using (StartServer(out var server)) + { + var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); + try + { + await connection.StartAsync().OrTimeout(); + var expectedValue = 0; + var streamTo = 5; + var asyncEnumerable = connection.StreamAsync("Stream", streamTo); + await foreach (var streamValue in asyncEnumerable) + { + Assert.Equal(expectedValue, streamValue); + expectedValue++; + } + + Assert.Equal(streamTo, expectedValue); + } + catch (Exception ex) + { + LoggerFactory.CreateLogger().LogError(ex, "{ExceptionType} from test", ex.GetType().FullName); + throw; + } + finally + { + await connection.DisposeAsync().OrTimeout(); + } + } + } + + [Theory] + [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))] + [LogLevel(LogLevel.Trace)] + public async Task StreamAsyncDoesNotStartIfTokenAlreadyCanceled(string protocolName, HttpTransportType transportType, string path) + { + bool ExpectedErrors(WriteContext writeContext) + { + return writeContext.LoggerName == DefaultHubDispatcherLoggerName && + writeContext.EventId.Name == "FailedInvokingHubMethod"; + } + var protocol = HubProtocols[protocolName]; + using (StartServer(out var server, ExpectedErrors)) + { + var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); + try + { + await connection.StartAsync().OrTimeout(); + + var cts = new CancellationTokenSource(); + cts.Cancel(); + + var ex = Assert.ThrowsAsync(async () => + { + var stream = connection.StreamAsync("Stream", 5, cts.Token); + await foreach (var streamValue in stream) + { + Assert.True(false, "Expected an exception from the streaming invocation."); + } + }); + } + catch (Exception ex) + { + LoggerFactory.CreateLogger().LogError(ex, "{ExceptionType} from test", ex.GetType().FullName); + throw; + } + finally + { + await connection.DisposeAsync().OrTimeout(); + } + } + } + + [Theory] + [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))] + [LogLevel(LogLevel.Trace)] + public async Task StreamAsyncCanBeCanceled(string protocolName, HttpTransportType transportType, string path) + { + var protocol = HubProtocols[protocolName]; + using (StartServer(out var server)) + { + var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); + try + { + await connection.StartAsync().OrTimeout(); + + var cts = new CancellationTokenSource(); + + var stream = connection.StreamAsync("Stream", 5, cts.Token); + var results = new List(); + + var enumerator = stream.GetAsyncEnumerator(); + await Assert.ThrowsAsync(async () => + { + while (await enumerator.MoveNextAsync()) + { + results.Add(enumerator.Current); + cts.Cancel(); + } + }); + + Assert.Single(results); + Assert.Equal(0, results[0]); + } + catch (Exception ex) + { + LoggerFactory.CreateLogger().LogError(ex, "{ExceptionType} from test", ex.GetType().FullName); + throw; + } + finally + { + await connection.DisposeAsync().OrTimeout(); + } + } + } + + [Theory] + [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))] + [LogLevel(LogLevel.Trace)] + public async Task StreamAsyncWithException(string protocolName, HttpTransportType transportType, string path) + { + bool ExpectedErrors(WriteContext writeContext) + { + return writeContext.LoggerName == DefaultHubDispatcherLoggerName && + writeContext.EventId.Name == "FailedInvokingHubMethod"; + } + + var protocol = HubProtocols[protocolName]; + using (StartServer(out var server, ExpectedErrors)) + { + var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); + try + { + await connection.StartAsync().OrTimeout(); + var asyncEnumerable = connection.StreamAsync("StreamException"); + var ex = await Assert.ThrowsAsync(async () => + { + await foreach (var streamValue in asyncEnumerable) + { + Assert.True(false, "Expected an exception from the streaming invocation."); + } + }); + + Assert.Equal("An unexpected error occurred invoking 'StreamException' on the server. InvalidOperationException: Error occurred while streaming.", ex.Message); + + } + catch (Exception ex) + { + LoggerFactory.CreateLogger().LogError(ex, "{ExceptionType} from test", ex.GetType().FullName); + throw; + } + finally + { + await connection.DisposeAsync().OrTimeout(); + } + } + } + [Theory] [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))] [LogLevel(LogLevel.Trace)] @@ -465,6 +662,48 @@ public async Task CanStreamToAndFromClientInSameInvocation(string protocolName, } } + [Theory] + [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))] + [LogLevel(LogLevel.Trace)] + public async Task StreamAsyncCanBeCanceledThroughGetEnumerator(string protocolName, HttpTransportType transportType, string path) + { + var protocol = HubProtocols[protocolName]; + using (StartServer(out var server)) + { + var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); + try + { + await connection.StartAsync().OrTimeout(); + var stream = connection.StreamAsync("Stream", 5 ); + var results = new List(); + + var cts = new CancellationTokenSource(); + + var enumerator = stream.GetAsyncEnumerator(cts.Token); + await Assert.ThrowsAsync(async () => + { + while (await enumerator.MoveNextAsync()) + { + results.Add(enumerator.Current); + cts.Cancel(); + } + }); + + Assert.Single(results); + Assert.Equal(0, results[0]); + } + catch (Exception ex) + { + LoggerFactory.CreateLogger().LogError(ex, "{ExceptionType} from test", ex.GetType().FullName); + throw; + } + finally + { + await connection.DisposeAsync().OrTimeout(); + } + } + } + [Theory] [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))] [LogLevel(LogLevel.Trace)] diff --git a/src/SignalR/server/Core/src/Internal/AsyncEnumerableAdapters.cs b/src/SignalR/common/Shared/AsyncEnumerableAdapters.cs similarity index 55% rename from src/SignalR/server/Core/src/Internal/AsyncEnumerableAdapters.cs rename to src/SignalR/common/Shared/AsyncEnumerableAdapters.cs index c0bef6ad7808..a0951b3e595c 100644 --- a/src/SignalR/server/Core/src/Internal/AsyncEnumerableAdapters.cs +++ b/src/SignalR/common/Shared/AsyncEnumerableAdapters.cs @@ -12,16 +12,75 @@ namespace Microsoft.AspNetCore.SignalR.Internal // True-internal because this is a weird and tricky class to use :) internal static class AsyncEnumerableAdapters { +#if NETCOREAPP3_0 public static IAsyncEnumerable MakeCancelableAsyncEnumerable(IAsyncEnumerable asyncEnumerable, CancellationToken cancellationToken = default) { return new CancelableAsyncEnumerable(asyncEnumerable, cancellationToken); } + public static IAsyncEnumerable MakeCancelableTypedAsyncEnumerable(IAsyncEnumerable asyncEnumerable, CancellationTokenSource cts) + { + return new CancelableTypedAsyncEnumerable(asyncEnumerable, cts); + } + public static IAsyncEnumerable MakeCancelableAsyncEnumerableFromChannel(ChannelReader channel, CancellationToken cancellationToken = default) { return MakeCancelableAsyncEnumerable(channel.ReadAllAsync(), cancellationToken); } + private class CancelableTypedAsyncEnumerable : IAsyncEnumerable + { + private readonly IAsyncEnumerable _asyncEnumerable; + private readonly CancellationTokenSource _cts; + + public CancelableTypedAsyncEnumerable(IAsyncEnumerable asyncEnumerable, CancellationTokenSource cts) + { + _asyncEnumerable = asyncEnumerable; + _cts = cts; + } + + public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + var enumerator = _asyncEnumerable.GetAsyncEnumerator(); + if (cancellationToken.CanBeCanceled) + { + var registration = cancellationToken.Register((ctsState) => + { + ((CancellationTokenSource)ctsState).Cancel(); + }, _cts); + + return new CancelableEnumerator(_asyncEnumerable.GetAsyncEnumerator(), registration); + } + + return enumerator; + } + + private class CancelableEnumerator : IAsyncEnumerator + { + private IAsyncEnumerator _asyncEnumerator; + private readonly CancellationTokenRegistration _cancellationTokenRegistration; + + public T Current => (T)_asyncEnumerator.Current; + + public CancelableEnumerator(IAsyncEnumerator asyncEnumerator, CancellationTokenRegistration registration) + { + _asyncEnumerator = asyncEnumerator; + _cancellationTokenRegistration = registration; + } + + public ValueTask MoveNextAsync() + { + return _asyncEnumerator.MoveNextAsync(); + } + + public ValueTask DisposeAsync() + { + _cancellationTokenRegistration.Dispose(); + return _asyncEnumerator.DisposeAsync(); + } + } + } + /// Converts an IAsyncEnumerable of T to an IAsyncEnumerable of object. private class CancelableAsyncEnumerable : IAsyncEnumerable { @@ -66,5 +125,6 @@ public ValueTask DisposeAsync() } } } +#endif } } diff --git a/src/SignalR/server/Core/src/Microsoft.AspNetCore.SignalR.Core.csproj b/src/SignalR/server/Core/src/Microsoft.AspNetCore.SignalR.Core.csproj index d26d4a30a9ef..6a2094ddae8b 100644 --- a/src/SignalR/server/Core/src/Microsoft.AspNetCore.SignalR.Core.csproj +++ b/src/SignalR/server/Core/src/Microsoft.AspNetCore.SignalR.Core.csproj @@ -11,6 +11,7 @@ +