Files
MPF/MPF.Core/Data/ProcessingQueue.cs

103 lines
2.8 KiB
C#
Raw Normal View History

2021-03-29 10:23:34 -07:00
using System;
#if NET20 || NET35
using System.Collections.Generic;
#else
2021-03-29 10:23:34 -07:00
using System.Collections.Concurrent;
#endif
using System.Threading;
2021-03-29 10:23:34 -07:00
using System.Threading.Tasks;
namespace MPF.Core.Data
2021-03-29 10:23:34 -07:00
{
2023-11-06 23:06:11 -05:00
public sealed class ProcessingQueue<T> : IDisposable
2021-03-29 10:23:34 -07:00
{
/// <summary>
/// Internal queue to hold data to process
/// </summary>
#if NET20 || NET35
private readonly Queue<T> InternalQueue;
#else
2021-03-29 10:23:34 -07:00
private readonly ConcurrentQueue<T> InternalQueue;
#endif
2021-03-29 10:23:34 -07:00
/// <summary>
/// Custom processing step for dequeued data
/// </summary>
private readonly Action<T> CustomProcessing;
/// <summary>
/// Cancellation method for the processing task
/// </summary>
private readonly CancellationTokenSource TokenSource;
2021-03-29 10:23:34 -07:00
public ProcessingQueue(Action<T> customProcessing)
{
#if NET20 || NET35
this.InternalQueue = new Queue<T>();
#else
2021-03-29 10:23:34 -07:00
this.InternalQueue = new ConcurrentQueue<T>();
#endif
2021-03-29 10:23:34 -07:00
this.CustomProcessing = customProcessing;
this.TokenSource = new CancellationTokenSource();
#if NET20 || NET35
Task.Run(() => ProcessQueue());
#elif NET40
Task.Factory.StartNew(() => ProcessQueue());
2023-11-20 13:15:06 -05:00
#else
2021-04-01 15:10:43 -07:00
Task.Run(() => ProcessQueue(), this.TokenSource.Token);
2023-11-20 13:15:06 -05:00
#endif
2021-03-29 10:50:43 -07:00
}
/// <summary>
/// Dispose the current instance
/// </summary>
2021-11-26 14:06:57 -08:00
public void Dispose() => this.TokenSource.Cancel();
2021-03-29 10:50:43 -07:00
/// <summary>
/// Enqueue a new item for processing
/// </summary>
/// <param name="item"></param>
2023-11-20 13:15:06 -05:00
public void Enqueue(T? item)
2021-03-29 10:50:43 -07:00
{
2021-04-01 19:08:39 -07:00
// Only accept new data when not cancelled
2023-10-07 01:02:21 -04:00
if (item != null && !this.TokenSource.IsCancellationRequested)
2021-04-01 15:10:43 -07:00
this.InternalQueue.Enqueue(item);
2021-03-29 10:23:34 -07:00
}
/// <summary>
/// Process
/// </summary>
private void ProcessQueue()
{
while (true)
{
// Nothing in the queue means we get to idle
#if NET20 || NET35
if (InternalQueue.Count == 0)
#else
2023-11-06 23:06:11 -05:00
if (InternalQueue.IsEmpty)
#endif
2021-04-01 19:08:39 -07:00
{
if (this.TokenSource.IsCancellationRequested)
break;
Thread.Sleep(10);
2021-03-29 10:23:34 -07:00
continue;
2021-04-01 19:08:39 -07:00
}
2021-03-29 10:23:34 -07:00
#if NET20 || NET35
// Get the next item from the queue and invoke the lambda, if possible
this.CustomProcessing?.Invoke(this.InternalQueue.Dequeue());
#else
2021-03-29 10:23:34 -07:00
// Get the next item from the queue
2023-10-07 01:02:21 -04:00
if (!this.InternalQueue.TryDequeue(out var nextItem))
2021-03-29 10:23:34 -07:00
continue;
// Invoke the lambda, if possible
this.CustomProcessing?.Invoke(nextItem);
#endif
2021-03-29 10:23:34 -07:00
}
}
}
}