public static async Task ParseAsync(string filePath, CloudFrontRecord[] items) { if (File.Exists(filePath)) { using (var fileStream = File.OpenRead(filePath)) using (var decompressionStream = new GZipStream(fileStream, CompressionMode.Decompress)) { var pipeReader = StreamConnection.GetReader(decompressionStream); var position = 0; while (true) { var result = await pipeReader.ReadAsync(); var buffer = result.Buffer; ParseLines(items, ref buffer, ref position); // Tell the PipeReader how much of the buffer we have consumed pipeReader.AdvanceTo(buffer.Start, buffer.End); // Stop reading if there's no more data coming if (result.IsCompleted) { break; } } // Mark the PipeReader as complete pipeReader.Complete(); } } }
public static async Task <List <Event> > ProcessFeed(Stream stream) { var reader = StreamConnection.GetReader(stream); var events = new List <Event>(); void catchEvent(Event ev) => events.Add(ev); await GetEvents(reader, catchEvent); return(events); }
async Task IDuplexMessageStream.OpenAsync(CancellationToken cancellationToken) { ReadCompleted = false; WriteCompleted = false; readStream = await readProvider(cancellationToken).ConfigureAwait(false); writeStream = writeProvider == readProvider ? readStream : await writeProvider(cancellationToken).ConfigureAwait(false); reader = StreamConnection.GetReader(readStream); writer = StreamConnection.GetWriter(writeStream); }
private static async Task Main(string[] args) { // run for 90 seconds var timeout = TimeSpan.FromSeconds(90); // in reality this will likely never be reached, but it is useful to guard against // conditions where the queue isn't drained, or not drained fast enough. const int maxNonKeyEventRetention = 128; var source = new CancellationTokenSource(timeout); var token = source.Token; var handle = Kernel32.GetStdHandle(Kernel32.StdHandleType.STD_INPUT_HANDLE); if (!Kernel32.GetConsoleMode(handle, out Kernel32.CONSOLE_INPUT_MODE mode)) { throw NativeMethods.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); } mode |= Kernel32.CONSOLE_INPUT_MODE.ENABLE_WINDOW_INPUT; mode |= Kernel32.CONSOLE_INPUT_MODE.ENABLE_VIRTUAL_TERMINAL_INPUT; mode &= ~Kernel32.CONSOLE_INPUT_MODE.ENABLE_ECHO_INPUT; mode &= ~Kernel32.CONSOLE_INPUT_MODE.ENABLE_LINE_INPUT; if (!Kernel32.SetConsoleMode(handle, mode)) { throw NativeMethods.GetExceptionForLastWin32Error(); } // base our provider/consumer on a bounded queue to keep memory usage under control var events = new BlockingCollection <Kernel32.INPUT_RECORD>( new ConcurrentBoundedQueue <Kernel32.INPUT_RECORD>(maxNonKeyEventRetention)); // Task that will consume non-key events asynchronously var consumeEvents = Task.Run(() => { Console.WriteLine("consumeEvents started"); try { while (!events.IsCompleted) { // blocking call var record = events.Take(token); Console.WriteLine("record: {0}", Enum.GetName(typeof(Kernel32.EVENT_TYPE), record.EventType)); } } catch (OperationCanceledException) { // timeout } Console.WriteLine("consumeEvents ended"); }, token); // Task that will watch for key events while feeding non-key events into our provider/consumer collection var readInputAndProduceEvents = Task.Run(async() => { //So, this is the key point - we cannot use the following or we lose all non-key events: // Stream stdin = Console.OpenStandardInput(); // get a unicode character stream over console input Stream stdin = new ReadConsoleInputStream(handle, events); // wrap in a System.IO.Pipelines.PipeReader to get clean async and span/memory usage var reader = StreamConnection.GetReader(stdin); while (!token.IsCancellationRequested) { // blocking call var result = await reader.ReadAsync(token); if (result.IsCanceled) { break; } var sequence = result.Buffer; var segment = sequence.Start; while (sequence.TryGet(ref segment, out var mem)) { // decode back from unicode var datum = Encoding.Unicode.GetString(mem.Span); Console.Write(datum); } reader.AdvanceTo(sequence.End); } }, token); Console.WriteLine("Running"); try { await Task.WhenAll(consumeEvents, readInputAndProduceEvents); } catch (OperationCanceledException) { // timeout } Console.WriteLine("press any key..."); Console.ReadKey(true); }
/// <summary> /// Receive multiple messages from a stream /// </summary> public static IAsyncEnumerable <T> ReceiveAsync <T>(Stream source, MessagePipeOptions options = default) => ReceiveAsync <T>(StreamConnection.GetReader(source, options.PipeOptions), options);