public SequentialMediaReaderAndProcessor(ICallback callback) { this.callback = callback; this.outputQueue = new BlockingProcessingQueue <OutputQueueEntry>(new UnderlyingOutputQueue()); this.cancellationTokenSource = new CancellationTokenSource(); this.processingTask = new Task(() => { ParallelOptions opts = new ParallelOptions(); //opts.MaxDegreeOfParallelism = 1; // uncomment that to simplify debugging Parallel.ForEach( MakeOutputQueue(), opts, callback.InitializeThreadLocalState, (token, state, tls) => { var entry = token.Value; entry.Output = entry.Input != null ? callback.ProcessRawData(entry.Input, tls, opts.CancellationToken) : null; token.Value = entry; token.MarkAsProcessed(); return(tls); }, (tls) => { } ); }); this.processingTask.Start(); }