47 lines
1.9 KiB
C#
47 lines
1.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Concurrent;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
public class SingleThreadTaskScheduler : TaskScheduler, IDisposable
|
|
{
|
|
private readonly BlockingCollection<Task> _tasks = new BlockingCollection<Task>();
|
|
private readonly Thread _thread;
|
|
public SynchronizationContext SyncContext { get; private set; }
|
|
|
|
public SingleThreadTaskScheduler(string threadName)
|
|
{
|
|
var tcs = new TaskCompletionSource<bool>();
|
|
_thread = new Thread(() =>
|
|
{
|
|
// Creiamo il contesto di sincronizzazione personalizzato
|
|
SyncContext = new SingleThreadSynchronizationContext(this);
|
|
SynchronizationContext.SetSynchronizationContext(SyncContext);
|
|
tcs.SetResult(true);
|
|
|
|
foreach (var task in _tasks.GetConsumingEnumerable())
|
|
{
|
|
base.TryExecuteTask(task);
|
|
}
|
|
})
|
|
{ IsBackground = true, Name = threadName };
|
|
_thread.Start();
|
|
tcs.Task.Wait(); // Aspetta che il thread sia pronto col suo contesto
|
|
}
|
|
|
|
private class SingleThreadSynchronizationContext : SynchronizationContext
|
|
{
|
|
private readonly SingleThreadTaskScheduler _sch;
|
|
public SingleThreadSynchronizationContext(SingleThreadTaskScheduler sch) => _sch = sch;
|
|
public override void Post(SendOrPostCallback d, object state)
|
|
=> Task.Factory.StartNew(() => d(state), CancellationToken.None, TaskCreationOptions.None, _sch);
|
|
}
|
|
|
|
protected override void QueueTask(Task task) => _tasks.Add(task);
|
|
protected override bool TryExecuteTaskInline(Task task, bool prev)
|
|
=> Thread.CurrentThread == _thread && base.TryExecuteTask(task);
|
|
protected override IEnumerable<Task> GetScheduledTasks() => _tasks;
|
|
public override int MaximumConcurrencyLevel => 1;
|
|
public void Dispose() => _tasks.CompleteAdding();
|
|
} |