public static void Go <TBuffer>( Func <TBuffer> newBufferFunc, ProducerDelegate <TBuffer> producer, ConsumerDelegate <TBuffer> consumer, CancellationToken cancel ) { BlockingCollection <TBuffer> unusedBuffers = new(); unusedBuffers.Add(newBufferFunc(), cancel); unusedBuffers.Add(newBufferFunc(), cancel); unusedBuffers.Add(newBufferFunc(), cancel); BlockingCollection <(int Count, TBuffer Buffer)> consumerQueue = new(); long total = 0; var producerTask = Task.Factory.StartNew( () => { while (!cancel.IsCancellationRequested) { var buffer = unusedBuffers.Take(cancel); producer(buffer, out var batchCount); if (batchCount <= 0) { break; } consumerQueue.Add((batchCount, buffer)); } consumerQueue.CompleteAdding(); }, cancel, TaskCreationOptions.LongRunning, TaskScheduler.Default); var consumerTask = Task.Factory.StartNew( () => { try { while (!cancel.IsCancellationRequested) { var(count, buffer) = consumerQueue.Take(cancel); total += count; consumer(buffer, count, total); unusedBuffers.Add(buffer); } } catch (InvalidOperationException) { // thrown when we try to Take after CompleteAdding; just end the loop } }, cancel, TaskCreationOptions.LongRunning, TaskScheduler.Default); producerTask.ConfigureAwait(false).GetAwaiter().GetResult(); consumerTask.ConfigureAwait(false).GetAwaiter().GetResult(); }
/// <summary> Send a message to a EMS destination. The callback gives access to /// the EMS session and MessageProducer in order to do more complex /// send operations. /// </summary> /// <param name="del">delegate that exposes the session/producer pair /// </param> /// <returns> the result object from working with the session /// </returns> /// <exception cref="EMSException">If there is any problem accessing the EMS API</exception> public object Execute(ProducerDelegate del) { return Execute(new ProducerCreatorCallback(this, del)); }
public ProducerCreatorCallback(EmsTemplate jmsTemplate, ProducerDelegate producerDelegate) { this.jmsTemplate = jmsTemplate; this.producerDelegate = producerDelegate; }