Example #1
0
 public ReportProgress()
 {
     // 1 writer : n reader
     _channel = System.Threading.Channels.Channel.CreateUnbounded <AbReport>(new System.Threading.Channels.UnboundedChannelOptions
     {
         SingleWriter = true,
     });
 }
Example #2
0
 public MessageEventBus()
 {
     _channel = System.Threading.Channels.Channel.CreateUnbounded <T>(new System.Threading.Channels.UnboundedChannelOptions()
     {
         SingleReader = true,
     });
     _readerTask = Task.CompletedTask;
     _cancellationTokenSource = new CancellationTokenSource();
 }
Example #3
0
        public MessageEventBus(ILogger <MessageEventBus <T> > logger)
        {
            _logger  = logger ?? throw new ArgumentNullException(nameof(logger));
            _channel = System.Threading.Channels.Channel.CreateUnbounded <T>(new System.Threading.Channels.UnboundedChannelOptions()
            {
                SingleReader = true,
            });
            _cancellationTokenSource = new CancellationTokenSource();

            _readerTask  = Task.CompletedTask;
            _subscribers = Array.Empty <IMessageSubscriber <T> >();
        }
Example #4
0
 public MessageChannel()
 {
     Channel = System.Threading.Channels.Channel.CreateUnbounded <Message>();
 }
        public override async Task GetStockStream(IAsyncStreamReader <StockRequest> requestStream,
                                                  IServerStreamWriter <StockPerDateReply> responseStream, ServerCallContext context)
        {
            var token = context.CancellationToken;

            // we'll use a channel here to handle in-process 'messages'
            // concurrently being written to and read from the channel.
            var channel = Channel.CreateUnbounded <StockPerDateReply>();

            // background task which uses async streams to write each forecast from the channel to the response steam.
            _ = Task.Run(async() =>
            {
                await foreach (var stock in channel.Reader.ReadAllAsync(token))
                {
                    await responseStream.WriteAsync(stock);
                }
            }, token);

            // a list of tasks handling requests concurrently
            var getStockRequestTasks = new List <Task>();

            try
            {
                // async streams used to process each request from the stream as they are receieved
                await foreach (var request in requestStream.ReadAllAsync())
                {
                    _logger.LogInformation($"Getting stock-data for {request.Symbol}");
                    // start and add the request handling task
                    getStockRequestTasks.Add(GetStockDataAsync(request.Symbol, request.Date.ToDateTime()));
                }

                _logger.LogInformation("Client finished streaming");
            }
            catch (Exception e)
            {
                _logger.LogError(e, "An exception occurred");
            }

            // wait for all responses to be written to the channel
            // from the concurrent tasks handling each request
            await Task.WhenAll(getStockRequestTasks);

            channel.Writer.TryComplete();

            //  wait for all responses to be read from the channel and streamed as responses
            await channel.Reader.Completion;

            _logger.LogInformation("Completed response streaming");

            // a local function which defines a task to handle a town forecast request
            // it produces 10 forecasts for each town, simulating a 0.5s time to gather each forecast
            // multiple instances of this will run concurrently for each recieved request
            async Task GetStockDataAsync(string symbol, DateTime date)
            {
                var stock = await _stockService.SearchStock(symbol, date, token);

                await Task.Delay(150, token); // look busy

                // write the forecast to the channel which will be picked up concurrently by the channel reading background task
                await channel.Writer.WriteAsync(
                    new StockPerDateReply
                {
                    Symbol     = stock.Symbol,
                    Date       = stock.Date.ToTimestamp(),
                    BestPrice  = stock.High.FromDecimal(),
                    WorstPrice = stock.Low.FromDecimal(),
                }, token);
            }
        }