←back to thread

123 points eterm | 1 comments | | HN request time: 0.339s | source
Show context
yakz ◴[] No.43925685[source]
There are some events you can handle:

https://learn.microsoft.com/en-us/dotnet/api/system.servicem...

https://learn.microsoft.com/en-us/dotnet/api/system.servicem...

Could you use these to cancel the stream?

replies(1): >>43944234 #
1. junto ◴[] No.43944234[source]
This is the route I would go too, but quite honestly once you’re using the more non-standard WCF bindings in CoreWCF, you’re kind of playing with fire anyway. Microsoft never really intended to support WCF and SOAP in Core since it relied on so much Windows API’s under the hood in .NET Framework and they only added some support behind CoreWCF because so many enterprise customers still had SOAP and .NET services flying about that they had pressure to support something in this area.

public class StreamingService : IStreamingService { private readonly ILogger<StreamingService> _logger;

    public StreamingService(ILogger<StreamingService> logger)
    {
        _logger = logger;
    }

    public Stream GetRandomStream()
    {
        var random = Random.Shared;
        var isClientConnected = true;

        var context = OperationContext.Current;
        context.InstanceContext.Closed += (s, e) =>
        {
            _logger.LogInformation("Client closed connection.");
            isClientConnected = false;
        };
        context.InstanceContext.Faulted += (s, e) =>
        {
            _logger.LogWarning("Client connection faulted.");
            isClientConnected = false;
        };

        return new MonitorableRandomStream(random, () => isClientConnected, _logger);
    }
}

public class MonitorableRandomStream : Stream { private readonly Random _random; private readonly Func<bool> _isClientConnected; private readonly ILogger _logger; private long _sequence;

    public MonitorableRandomStream(Random random, Func<bool> isClientConnected, ILogger logger)
    {
        _random = random;
        _isClientConnected = isClientConnected;
        _logger = logger;
    }

    public override bool CanRead => true;
    public override bool CanSeek => false;
    public override bool CanWrite => false;
    public override long Length => throw new NotSupportedException();
    public override long Position { get => _sequence; set => throw new NotSupportedException(); }

    public override void Flush() {}

    public override int Read(byte[] buffer, int offset, int count)
    {
        if (!_isClientConnected())
        {
            _logger.LogInformation("Stopping stream: client disconnected.");
            return 0;
        }

        var span = new Span<byte>(buffer, offset, count);
        _random.NextBytes(span);
        _sequence += count;
        return count;
    }

    public override int Read(Span<byte> buffer)
    {
        if (!_isClientConnected())
        {
            _logger.LogInformation("Stopping stream: client disconnected.");
            return 0;
        }

        _random.NextBytes(buffer);
        _sequence += buffer.Length;
        return buffer.Length;
    }

    public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
    public override void SetLength(long value) => throw new NotSupportedException();
    public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
}