Files
Mapo-IOB-WIN/IOB-UT-NEXT/Services/Core/SingleThreadTaskScheduler.cs
T
2026-05-21 19:33:58 +02:00

92 lines
2.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
namespace IOB_UT_NEXT.Services.Core
{
public class SingleThreadTaskScheduler : TaskScheduler, IDisposable
{
#region Public Constructors
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
}
#endregion Public Constructors
#region Public Properties
public override int MaximumConcurrencyLevel => 1;
public SynchronizationContext SyncContext { get; private set; }
#endregion Public Properties
#region Public Methods
public void Dispose() => _tasks.CompleteAdding();
#endregion Public Methods
#region Protected Methods
protected override IEnumerable<Task> GetScheduledTasks() => _tasks;
protected override void QueueTask(Task task) => _tasks.Add(task);
protected override bool TryExecuteTaskInline(Task task, bool prev)
=> Thread.CurrentThread == _thread && base.TryExecuteTask(task);
#endregion Protected Methods
#region Private Fields
private readonly BlockingCollection<Task> _tasks = new BlockingCollection<Task>();
private readonly Thread _thread;
#endregion Private Fields
#region Private Classes
private class SingleThreadSynchronizationContext : SynchronizationContext
{
#region Public Constructors
public SingleThreadSynchronizationContext(SingleThreadTaskScheduler sch) => _sch = sch;
#endregion Public Constructors
#region Public Methods
public override void Post(SendOrPostCallback d, object state)
=> Task.Factory.StartNew(() => d(state), CancellationToken.None, TaskCreationOptions.None, _sch);
#endregion Public Methods
#region Private Fields
private readonly SingleThreadTaskScheduler _sch;
#endregion Private Fields
}
#endregion Private Classes
}
}