Files
Mapo-IOB-WIN/IOB-UT-NEXT/SingleThreadTaskScheduler.cs

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();
}