'SignalR: Cancellation in Case of Client to Server Streaming makes code buggy in case of dotnet client

I’m trying to send a stream from client to server from a dotnet client to another dotnet server through sending an invocation to a method on server hub as follows:

// Method on Server Hub which should read the stream

public async Task UploadChannelReader(ChannelReader<string> stream, CancellationToken cancellationToken)
{
    while (await stream.WaitToReadAsync(cancellationToken))
    {
        var item = await stream.ReadAsync(cancellationToken);
        Console.WriteLine(item);
    }
}

My implementation on dotnet client is as shown below:

// My method on dotnet client which used to invoke method on server

public async Task SendChannelStream(CounterInput counter, CancellationToken cancellationToken)
{
    if (_hubConnection.State == HubConnectionState.Disconnected)
    {
        await _hubConnection.StartAsync();
    }

    var channel = Channel.CreateBounded<string>(10);
    await _hubConnection.SendAsync(ServerChatEvents.UploadChannelReader, channel.Reader, cancellationToken);
    await WriteToChannel(channel.Writer, counter, cancellationToken);
}

private async Task WriteToChannel(ChannelWriter<string> writer, CounterInput counter, CancellationToken cancellationToken)
{
    Exception writeException = null;
    try
    {
        await writer.WriteAsync("This is the first item sent from client to server", cancellationToken);
        await writer.WriteAsync("This is the second item sent from client to server which can be received immidiately", cancellationToken);
        await Task.Delay(counter.Delay, cancellationToken);
        await writer.WriteAsync("This is the third item sent from client to server after a delay", cancellationToken);
        await writer.WriteAsync("After this item we complete the writer and so the reader should mark completed!", cancellationToken);
    }
    catch (System.Exception ex)
    {
        writeException = ex;
        Console.WriteLine(ex.Message);
    }
    finally
    {
        writer.Complete(writeException);
    }
}

Where _hubConnection is a HubConnection to the Server hub.

The code does not work and I am not sure even if it cancelled in dotnet client or dotnet hub server. But after removing the cancellationToken from the server hub method signature it works.

I think this is the correct behaviour since the cancellation from client is equal to not sending stream anymore which catch by server code automatically due to async nature of channel reader/writer or IAsyncEnumerable. But from a debugging point of view, it is really hard to find it out for me (...it has taken one full day!).

My questions are:

  1. Why in the case of using the cancellation token in hub method signature, it doesn't work? (seems it cancels just right after calling the method)
  2. Where does the cancellation take place? In dotnet client or in hub?


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source