The following demonstrates a custom task scheduler that maintains a fixed number of threads and does not allow inline execution. The code that tests the scheduler will cause a deadlock, because there are more waiting Tasks than there are working threads.

using System;

using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks;

namespace Deadlocked_Task_Scheduler {

class Deadlocked_Task_Scheduler: TaskScheduler, IDisposable { private BlockingCollection<Task> taskOueue; private Thread[] threads;

public Deadlocked_Task_Scheduler(int concurrency) { // initialize the collection and the thread array taskOueue = new BlockingCollection<Task>(); threads = new Thread[concurrency]; // create and start the threads for (int i = 0; i < threads.Length; i++) { (threads[i] = new Thread(() => {

// loop while the blocking collection is not // complete and try to execute the next task foreach (Task t in taskOueue.GetConsumingEnumerable()) { TryExecuteTask(t);

protected override void OueueTask(Task task) {

if (task.CreationOptions.HasFlag(TaskCreationOptions.LongRunning)) { // create a dedicated thread to execute this task new Thread(() => {

// add the task to the queue taskOueue.Add(task);

protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyOueued) {

// disallow all inline execution return false;

public override int MaximumConcurrencyLevel { get {

return threads.Length;

protected override IEnumerable<Task> GetScheduledTasks() { return taskOueue.ToArray();

public void Dispose() {

// mark the collection as complete taskQueue.CompleteAdding(); // wait for each of the threads to finish foreach (Thread t in threads) { t.Join();

class Test_Deadlocked_Task_Scheduler { static void Main(string[] args) {

// create the scheduler Deadlocked_Task_Scheduler scheduler = new Deadlocked_Task_Scheduler(5);

// create a token source CancellationTokenSource tokenSource = new CancellationTokenSource();

tasks[i] = Task.Factory.StartNew((object stateObj) => { int index = (int)stateObj; if (index < tasks.Length - 1) {

Console.WriteLine("Task {0} waiting for {1}", index, index + 1); tasks[index + 1].Wait();

Console.WriteLine("Task {0} complete", index); }, i, tokenSource.Token, TaskCreationOptions.None, scheduler);


Console.WriteLine("All tasks complete");

// wait for input before exiting Console.WriteLine("Press enter to finish"); Console.ReadLine();

0 0

Post a comment