Skip to content

Instantly share code, notes, and snippets.

@aienabled
Created April 18, 2023 15:28
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 aienabled/2f4ca9337b3f9a78aeaf03876f25c9be to your computer and use it in GitHub Desktop.
Save aienabled/2f4ca9337b3f9a78aeaf03876f25c9be to your computer and use it in GitHub Desktop.
C# single-threaded task execution
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
public static class TaskThreadSynchronizer
{
private static readonly object objLock = new();
private static readonly ConcurrentQueue<BaseQueuedTask> queue = new();
private static Thread thread;
public static Task<T> ProcessAsync<T>(Func<Task<T>> createTask)
{
lock (objLock)
{
if (thread is null)
{
thread = new Thread(ThreadMethod)
{
Name = "Synchronized processing thread",
IsBackground = true
};
thread.Start();
}
}
var queuedTask = new QueuedTask<T>(createTask);
queue.Enqueue(queuedTask);
return queuedTask.CompletionSource.Task;
}
private static void ThreadMethod()
{
while (true)
{
Thread.Sleep(1);
while (queue.TryDequeue(out var queuedTask))
{
queuedTask.RunTask();
}
}
}
private abstract class BaseQueuedTask
{
public abstract void RunTask();
}
private class QueuedTask<T> : BaseQueuedTask
{
public readonly TaskCompletionSource<T> CompletionSource = new();
private readonly Func<Task<T>> Func;
public QueuedTask(Func<Task<T>> func)
{
this.Func = func;
}
public override void RunTask()
{
try
{
var task = this.Func();
task.Wait();
if (task.Exception is not null)
{
this.CompletionSource.SetException(task.Exception);
}
else
{
this.CompletionSource.SetResult(task.Result);
}
}
catch (AggregateException ex)
{
this.CompletionSource.SetException(ex.InnerException);
}
catch (Exception ex)
{
this.CompletionSource.SetException(ex);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment