Skip to content

Instantly share code, notes, and snippets.

@mzabsky
Created July 13, 2016 19:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mzabsky/796483d5fd9e603421d8812bddc5b6a4 to your computer and use it in GitHub Desktop.
Save mzabsky/796483d5fd9e603421d8812bddc5b6a4 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace ZabskyNet
{
// This code is for demonstration purposes only and is mean to be as simple as possible. Don't use this in production!
public enum TaskPriority
{
Low,
Normal,
High
}
public delegate void CustomThreadPoolTaskMethod(CustomThreadPool pool);
public class CustomThreadPoolTask
{
public TaskPriority Priority { get; set; }
public CustomThreadPoolTaskMethod Method { get; set; }
}
public class CustomThreadPool
{
// This is not a data structures lesson and .Net doesn't have a proper priority queue :)
private List<CustomThreadPoolTask> _tasks = new List<CustomThreadPoolTask>();
public CustomThreadPool(int numberOfThreads)
{
for (int i = 0; i < numberOfThreads; i++)
{
Thread thread = new Thread(this.PooledThreadBody);
thread.Start();
}
}
public void EnqueueTask(CustomThreadPoolTask task)
{
lock (_tasks)
{
_tasks.Add(task);
}
}
private void PooledThreadBody()
{
while (true)
{
// Grab first scheduled task of the highest priority in the "queue"
CustomThreadPoolTask taskToExecute;
lock (_tasks)
{
// Fortunately, IEnumerable OrderBy is stable.
taskToExecute = this._tasks.OrderBy(p => (int)p.Priority).FirstOrDefault();
// There are no scheduled tasks, currently.
if (taskToExecute == null)
{
// Try again in a moment.
Thread.Sleep(TimeSpan.FromSeconds(0.1));
continue;
}
_tasks.Remove(taskToExecute);
}
SynchronizationContext.SetSynchronizationContext(
new CustomThreadPoolSynchronizationContext(this, taskToExecute.Priority)
);
taskToExecute.Method(this);
}
}
}
internal class CustomThreadPoolSynchronizationContext : SynchronizationContext
{
private readonly CustomThreadPool _threadPool;
private readonly TaskPriority _priority;
public CustomThreadPoolSynchronizationContext(CustomThreadPool threadPool, TaskPriority priority)
{
_threadPool = threadPool;
_priority = priority;
}
public override SynchronizationContext CreateCopy()
{
return new CustomThreadPoolSynchronizationContext(_threadPool, _priority);
}
public override void Post(SendOrPostCallback d, object state)
{
_threadPool.EnqueueTask(new CustomThreadPoolTask
{
Method = (pool) => d(state),
Priority = _priority
});
}
}
class Program
{
static void Main(string[] args)
{
var threadPool = new CustomThreadPool(2);
for (int i = 0; i < 10; i++)
{
var currentI = i; // Make sure correct I gets captured in the lambda
threadPool.EnqueueTask(new CustomThreadPoolTask
{
Method = async (pool) =>
{
Console.WriteLine("Task " + currentI + "A started " + Thread.CurrentThread.ManagedThreadId);
await Task.Delay(TimeSpan.FromSeconds(3));
Console.WriteLine("Task " + currentI + "A continued " + Thread.CurrentThread.ManagedThreadId);
pool.EnqueueTask(new CustomThreadPoolTask
{
Method = async (pool2) =>
{
Console.WriteLine("Task " + currentI + "B started " + Thread.CurrentThread.ManagedThreadId);
await Task.Delay(TimeSpan.FromSeconds(3));
Console.WriteLine("Task " + currentI + "B continued " + Thread.CurrentThread.ManagedThreadId);
}
});
}
});
}
Console.ReadKey();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment