async Task Test() { var _asyncStack = new AsyncCollection <int>( new ConcurrentStack <int>(), maxCount: 1); // This Add completes immediately. await _asyncStack.AddAsync(7); // This Add (asynchronously) waits for the 7 to be removed // before it enqueues the 13. await _asyncStack.AddAsync(13); _asyncStack.CompleteAdding(); while (true) { int item; try { item = await _asyncStack.TakeAsync(); } catch (InvalidOperationException) { break; } Trace.WriteLine(item); } }
private async Task Producer() { await _asyncCollection.AddAsync(7); await _asyncCollection.AddAsync(13); _asyncCollection.CompleteAdding(); }
async Task EnableReading() { try { while (true) { var packet = await Stream.ReadMessageAsync(CancelSource.Token); if (packet == null) { RemoteDisconnect(); return; } ReceivingStream.ReadMessage(packet); while (ReceivingStream.HasMessage) { await ReceiveQueue.AddAsync(ReceivingStream.GetMessage()); } } } catch { RemoteDisconnect(); } }
public async Task Process(CancellationToken cancellationToken) { while (true) { // The AsyncProducerConsumerQueue should never be in a completed state, // so DequeueAsync should only throw OperationCanceledException, // in which case the item should still be in the queue. var item = await input.TakeAsync(cancellationToken).ConfigureAwait(false); logger.ConditionalDebug("Processing \"{0}\"", item.Description); try { await torrentClientStatus.WaitAsync().ConfigureAwait(false); await AddItemAsync(item, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { // Put the item back in the queue, so it is not lost. // Do not provide a CancellationToken to try to ensure that the operation succeeds. logger.Warn("Adding \"{0}\" back into the queue due to failure", item.Description); await input.AddAsync(item).ConfigureAwait(false); if (ex is OperationCanceledException) { throw; } else { logger.Error(ex, "Adding torrent failed"); } } } }
private static void StartProducer() { Task.Factory.StartNew(async() => { var counter = 0; while (++counter <= 50) { await asyncCollection.AddAsync(counter); await asyncCollection.AddAsync(++counter); Thread.Sleep(TimeSpan.FromSeconds(0.1)); } asyncCollection.CompleteAdding(); }); }
public async Task FillSegmentAsync(ArraySegment <byte> segment, int newSize, CancellationToken token) { if (segment.Count != newSize) { _offsetSize[segment.Offset] = newSize; } await _filledSegments.AddAsync(segment.Offset, token); }
async void Example14() { //限流 AsyncCollection <int> _asyncStack = new AsyncCollection <int>(new ConcurrentStack <int>(), maxCount: 1); await _asyncStack.AddAsync(7); //这个添加过程会立即完成。 await _asyncStack.AddAsync(13); //这个添加(异步地)等待,直到7被移除,然后才会加入13。 _asyncStack.CompleteAdding(); //多个消费者 while (true) { //var takeResult = await _asyncStack.TryTaskAsync(); //if (!takeResult.Success) break; //Trace.WriteLine(takeResult.Item); } }
/// <summary> /// Checks if the command request is allowed and enqueues it internally if that is the case. /// If it is illegal, an exception is thrown that can be sent back to the client. /// </summary> /// <param name="command">Command to enqueue</param> /// <returns>Task</returns> /// <exception cref="ArgumentException">Thrown if the command type is illegal</exception> private async Task EnqueueCommand(BaseCommand command) { if (SupportedCommands.Contains(command.GetType()) || Command.SupportedCommands.Contains(command.GetType())) { await _commandQueue.AddAsync(command); } else { throw new ArgumentException($"Invalid command {command.Command} (wrong mode?)"); } }
async void Example13() { AsyncCollection <int> _asyncStack = new AsyncCollection <int>(new ConcurrentStack <int>()); //后进先出(栈) AsyncCollection <int> _asyncBag = new AsyncCollection <int>(new ConcurrentBag <int>()); //无序(包) //在栈的项目次序上有竞态条件。单线程中如果先运行生存者代码,后运行消费者代码,那项目的次序就像一个普通的栈 //生存者代码 await _asyncStack.AddAsync(7); await _asyncStack.AddAsync(13); _asyncStack.CompleteAdding(); //消费者代码 //先显示“13”,后显示“7” while (await _asyncStack.OutputAvailableAsync()) { Trace.WriteLine(_asyncStack.TakeAsync()); } //当生产者和消费者都并发运行时(这是常见情况),消费者总是会得到最近加入的项目。这导致这个集合从整体上看不像是一个栈。当然了,包是根本没有次序的。 }
async Task Test() { var _asyncStack = new AsyncCollection <int>( new ConcurrentStack <int>()); var _asyncBag = new AsyncCollection <int>( new ConcurrentBag <int>()); // Producer code await _asyncStack.AddAsync(7); await _asyncStack.AddAsync(13); _asyncStack.CompleteAdding(); // Consumer code // Displays "13" followed by "7". while (await _asyncStack.OutputAvailableAsync()) { Trace.WriteLine(await _asyncStack.TakeAsync()); } }
public async Task Process(CancellationToken cancellationToken) { while (await input.OutputAvailableAsync(cancellationToken).ConfigureAwait(false)) { var item = await input.TakeAsync(cancellationToken).ConfigureAwait(false); logger.ConditionalDebug("Processing \"{0}\"", item.Title); // Do not pass a CancellationToken, so that the operation cannot be interrupted. var torrentItem = new Torrent(item.Url, true, item.Title); await output.AddAsync(torrentItem).ConfigureAwait(false); } }
private async Task EnqueueMatchAsync(FeedItem item, CancellationToken cancellationToken) { logger.ConditionalDebug("Enqueueing matched item: \"{0}\"", item.Title); if (Uri.TryCreate(item.Link, UriKind.Absolute, out Uri matchUrl)) { var match = new FeedItemMatch(item.Title, matchUrl); await output.AddAsync(match, cancellationToken).ConfigureAwait(false); } else { logger.Error("Failed to create Uri from \"{0}\". Ignoring item.", item.Link); } }
/// <summary> /// Called by the <see cref="Code"/> implementation to check if the client wants to intercept a G/M/T-code /// </summary> /// <param name="code">Code to intercept</param> /// <returns>True if the code has been resolved</returns> /// <exception cref="OperationCanceledException">Code has been cancelled</exception> private async Task <bool> Intercept(Code code) { // Avoid race conditions. A client can deal with only one code at once! using (await _lock.LockAsync(Program.CancelSource.Token)) { // Send it to the IPC client await _codeQueue.AddAsync(code); // Keep on processing commands from the interceptor until a handling result is returned. // This must be either a Cancel, Ignore, or Resolve instruction! try { if (await _commandQueue.OutputAvailableAsync(Program.CancelSource.Token)) { BaseCommand command = await _commandQueue.TakeAsync(Program.CancelSource.Token); // Code is cancelled. This invokes an OperationCanceledException on the code's task. if (command is Cancel) { throw new OperationCanceledException(); } // Code is resolved with a given result and the request is acknowledged if (command is Resolve resolveCommand) { code.Result = (resolveCommand.Content == null) ? new CodeResult() : new CodeResult(resolveCommand.Type, resolveCommand.Content); return(true); } // Code is ignored. Don't do anything } } catch (Exception e) when(!(e is OperationCanceledException)) { _codeQueue.CompleteAdding(); Console.WriteLine($"[err] Interception handler enocuntered an exception: {e}"); } } return(false); }
/// <summary> /// Called by the <see cref="Code"/> implementation to check if the client wants to intercept a G/M/T-code /// </summary> /// <param name="code">Code to intercept</param> /// <returns>True if the code has been resolved</returns> /// <exception cref="OperationCanceledException">Code has been cancelled</exception> private async Task <bool> Intercept(Code code) { // Send it to the IPC client await _codeQueue.AddAsync(code); // Keep on processing commands from the interceptor until a handling result is returned. // This must be either a Cancel, Ignore, or Resolve instruction! try { if (await _commandQueue.OutputAvailableAsync(Program.CancellationToken)) { BaseCommand command = await _commandQueue.TakeAsync(Program.CancellationToken); // Code is cancelled. This invokes an OperationCanceledException on the code's task. if (command is Cancel) { throw new OperationCanceledException(); } // Code is resolved with a given result and the request is acknowledged if (command is Resolve resolveCommand) { code.Result = (resolveCommand.Content == null) ? new CodeResult() : new CodeResult(resolveCommand.Type, resolveCommand.Content); return(true); } // Code is ignored. Don't do anything } } catch (Exception e) when(!(e is OperationCanceledException)) { _codeQueue.CompleteAdding(); Connection.Logger.Error(e, "Interception processor caught an exception"); } return(false); }
public DfTask Run(Func <Task> action) { var task = new DfTask(); var currentListOfVisitedNodes = ListOfVisitedNodes.Current.Value ?? (ListOfVisitedNodes.Current.Value = new ListOfVisitedNodes()); var firstVisit = !currentListOfVisitedNodes.VisitedNodes.Contains(nodeId); if (firstVisit) { currentListOfVisitedNodes.VisitedNodes.Add(nodeId); } Func <Task> runAction = async() => { Exception exception = null; try { if (cancellationToken.IsCancellationRequested) { exception = new OperationCanceledException(cancellationToken); } else { await action(); } } catch (Exception ex) { exception = ex; } ListOfVisitedNodes.Current.Value = currentListOfVisitedNodes; DfTask.AsyncBlockingTask = null; if (exception == null) { task.SetResult(); } else { task.SetException(exception); } if (DfTask.AsyncBlockingTask != null) { await DfTask.AsyncBlockingTask; } }; Func <Task> actionToAddToCollection = Utilities.MakeActionRunInCurrentExecutionContextIfAny(runAction); ListOfVisitedNodes.Current.Value = null; if (firstVisit) { DfTask.AsyncBlockingTask = collection.AddAsync(actionToAddToCollection); } else { DfTask.AsyncBlockingTask = collectionForReentrantItems.AddAsync(actionToAddToCollection); } return(task); }
public async Task ReceiveAsync(byte[] data, CancellationToken cancellation) { using (var linked = CancellationTokenSource.CreateLinkedTokenSource(cancellation, CancelBrook.Token)) await ReadQueue.AddAsync(data, linked.Token); }
/// <summary> /// Merge received data into the object model /// </summary> /// <param name="module">Module that is supposed to be merged</param> /// <param name="json">JSON data</param> /// <returns>Asynchronous task</returns> public static Task MergeData(byte module, byte[] json) => _statusUpdates.AddAsync(new Tuple <byte, byte[]>(module, json));
async Task Main(string[] args) { //不可变集合是永远不会改变的集合,写入操作会返回新实例,不可变集合之间通常共享了大部分存储空间,浪费不大。多个线程访问安全 ///不可变栈 var list = ImmutableStack <int> .Empty; list = list.Push(13); list = list.Push(15); foreach (var item in list) { Console.WriteLine(item); } ///不可变队列 ImmutableQueue //不可变列表 //支持索引、不经常修改、可以被多个线程安全访问 var immutlist = ImmutableList <int> .Empty; immutlist = immutlist.Insert(0, 13); immutlist = immutlist.Insert(0, 7); //不可变set集合 //不需要存放重复内容,不经常修改,可以被多个线程安全访问 //ImmutableHashSet 不含重复元素的集合 //ImmutableSortedSet 已排序不含重复元素的集合 //不可变字典 //ImmutableSortedDictionary //ImmutableDictionary //线程安全集合是可同时被多个线程修改的可变集合,线程安全集合混合使用了细粒度锁定和无锁技术,优点是多个线程可安全地对其进行访问 //线程安全字典 //需要有一个键/值集合,多个线程同时读写时仍能保持同步 //ConcurrentDictionary var dictionary = new ConcurrentDictionary <int, string>(); //第一个委托把本来的键0转换成值zero,第二个委托把键0和原来的值转换成字典中修改后的值 zero,只有字典中已民存在这个键时,最后一个委托才会运行 dictionary[0] = "zero"; var newValue = dictionary.AddOrUpdate(0, key => "Zero", (key, oldValue) => "Zero1"); dictionary.TryGetValue(0, out string currentalue); Console.WriteLine(currentalue); dictionary.TryRemove(0, out string removeValue); //生产费消费者模型 //阻塞队列 //需要有一个管道,在进行之间传递消息或数据,例如一个线程下大装载数据,装载的同时把数据压进管道,与此同时,另一个线程在管道的接收端接收处理数据 //BlockingCollection 类可当做这种管道,阻塞队列,先进先出 限流 bounedCapacity属性 //不过如果用到这个的话,更推荐数据流 var blockqueue = new BlockingCollection <int>(); var blockqueueTask = Task.Factory.StartNew(() => { blockqueue.Add(7); blockqueue.Add(8); blockqueue.Add(9); blockqueue.CompleteAdding(); }); foreach (var item in blockqueue.GetConsumingEnumerable()) { Console.WriteLine(item); } await blockqueueTask; //阻塞栈和包 //首先有一个管道,在线程之间传递消息或数据,但不想(不需要)这个管道使用先进先出的语义 //blockingCollection 可以在创建时选择规则 var _blockingStack = new BlockingCollection <int>(new ConcurrentBag <int>()); //异步队列 //在代码的各个部分之间以选进先出的方式传递消息或数据 多个消费者时需要注意捕获InvalidOperationException异常 var _syncQueue = new BufferBlock <int>(); await _syncQueue.SendAsync(7); await _syncQueue.SendAsync(13); _syncQueue.Complete(); while (await _syncQueue.OutputAvailableAsync()) { Console.WriteLine(await _syncQueue.ReceiveAsync()); } //异步栈和包 //需要有一个管道,在程序的各个部分传递数据,但不希望先进先出 var _asyncStack = new AsyncCollection <int>(new ConcurrentBag <int>(), maxCount: 1); //这个添加操作会立即完成,下一个添加会等待7被移除后 await _asyncStack.AddAsync(7); _asyncStack.CompleteAdding(); while (await _asyncStack.OutputAvailableAsync()) { var taskReuslt = await _asyncStack.TryTakeAsync(); if (taskReuslt.Success) { Console.WriteLine(taskReuslt.Item); } } //阻塞/异步队列 //先进先出 足够灵活 同步或异步方式处理 var queue = new BufferBlock <int>(); await queue.SendAsync(1); queue.Complete(); while (await queue.OutputAvailableAsync()) { Console.WriteLine(await queue.ReceiveAsync()); } Console.WriteLine("Hello World!"); }
public async void SendAsync(byte[] message) { var packet = Data.AddSizeToMessage(message); await SendQueue.AddAsync(packet); }
public async Task FreeSegmentAsync(ArraySegment <byte> segment, CancellationToken token) { await _emptySegments.AddAsync(segment.Offset, token); }
async void ReceiveAsync() { try { while (true) { var packet = await ProtobufEx.DeserializeWithLengthPrefixAsync <MultiplexPacket>(Inner, PrefixStyle.Base128, CancelAll.Token); if (packet.SubstreamId != 0) { InboundSubstream = -packet.SubstreamId; } else if (InboundSubstream == 0) { throw new FormatException(); } MultiplexSubstream substream; bool created = false; lock (Substreams) { if (!Substreams.TryGetValue(InboundSubstream, out substream) && InboundSubstream < 0) { Substreams[InboundSubstream] = substream = new MultiplexSubstream(this, InboundSubstream); created = true; } } if (created) { await Pending.AddAsync(substream, CancelAll.Token); } if (substream != null) { if (packet.Data != null && packet.Data.Length > 0) { await substream.ReceiveAsync(packet.Data, CancelAll.Token); } if (packet.EndOfStream) { await substream.ReceiveEndOfStream(CancelAll.Token); } } } } catch (EndOfStreamException) { Dispose(); List <MultiplexSubstream> substreams; lock (Substreams) substreams = Substreams.Values.ToList(); foreach (var substream in substreams) { substream.Dispose(); } } catch (Exception e) { if (!CancelAll.Token.IsCancellationRequested) { Logger.Error(e); Dispose(); } } }
/// <summary> /// Waits for commands to be received and enqueues them in a concurrent queue so that a <see cref="Code"/> /// can decide when to cancel/resume/resolve the execution. /// </summary> /// <returns>Task that represents the lifecycle of the connection</returns> public override async Task Process() { try { do { // Read another code from the interceptor if (await _codeQueue.OutputAvailableAsync(Program.CancelSource.Token)) { Code code = await _codeQueue.TakeAsync(Program.CancelSource.Token); await Connection.Send(code); } else { break; } // Keep processing commands until an action for the code has been received BaseCommand command; do { // Read another command from the IPC connection command = await Connection.ReceiveCommand(); if (command == null) { break; } if (Command.SupportedCommands.Contains(command.GetType())) { // Interpret regular Command codes here object result = command.Invoke(); await Connection.SendResponse(result); } else if (SupportedCommands.Contains(command.GetType())) { // Send other commands to the task intercepting the code await _commandQueue.AddAsync(command); break; } else { // Take care of unsupported commands throw new ArgumentException($"Invalid command {command.Command} (wrong mode?)"); } }while (!Program.CancelSource.IsCancellationRequested); // Stop if the connection has been terminated if (command == null) { break; } }while (!Program.CancelSource.IsCancellationRequested); } catch (SocketException) { // IPC client has closed the connection } finally { _commandQueue.CompleteAdding(); _interceptors.TryRemove(this, out _); } }