public async Task IncreaseConcurrency() { int count = 0; var waitForFirstTwoItems = TaskSourceSlim.Create <object>(); // Event that will hold first two workers. var mre = new ManualResetEventSlim(false); var actionBlock = new ActionBlockSlim <int>( 2, n => { var currentCount = Interlocked.Increment(ref count); if (currentCount == 2) { // Notify the test that 2 items are processed. waitForFirstTwoItems.SetResult(null); } if (currentCount <= 2) { // This is the first or the second thread that should be blocked before we increase the number of threads. mre.Wait(TimeSpan.FromSeconds(100)); } Thread.Sleep(1); }); // Schedule work actionBlock.Post(1); actionBlock.Post(2); await waitForFirstTwoItems.Task; // The first 2 threads should be blocked in the callback in the action block, // but the count should be incremented Assert.Equal(2, count); var task = actionBlock.CompletionAsync(); // The task should not be completed yet! Assert.NotEqual(TaskStatus.RanToCompletion, task.Status); // This will cause another thread to spawn actionBlock.IncreaseConcurrencyTo(3); // Add more work actionBlock.Post(3); actionBlock.Complete(); // Release the first 2 threads mre.Set(); // Waiting for completion await task; // The new thread should run and increment the count Assert.Equal(3, count); }
/// <summary> /// Changes the concurrency level. /// </summary> public void IncreaseConcurrencyTo(int maxDegreeOfParallelism) { Contract.Requires(maxDegreeOfParallelism >= -1); maxDegreeOfParallelism = maxDegreeOfParallelism == -1 ? Environment.ProcessorCount : maxDegreeOfParallelism; if (maxDegreeOfParallelism > m_serializationQueue.DegreeOfParallelism) { m_serializationQueue.IncreaseConcurrencyTo(maxDegreeOfParallelism); } }