You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Zero/ZeroLevel/Services/Utils/Multiprocessor.cs

100 lines
2.9 KiB

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
namespace ZeroLevel.Utils
{
public class Multiprocessor<T>
: IDisposable
{
private BlockingCollection<T> _queue = new BlockingCollection<T>();
private List<Thread> _threads = new List<Thread>();
private bool _is_disposed = false;
private int _tasks_in_progress = 0;
public int Count => _queue.Count + _tasks_in_progress;
public Multiprocessor(Action<T> handler, int size, int stackSize = 1024 * 1024)
{
for (int i = 0; i < size; i++)
{
var t = new Thread(() =>
{
T item;
while (!_is_disposed)
{
try
{
if (_queue.TryTake(out item, 500))
{
Interlocked.Increment(ref _tasks_in_progress);
try
{
handler(item);
}
finally
{
Interlocked.Decrement(ref _tasks_in_progress);
}
}
}
catch (Exception ex)
{
Log.Error(ex, "[Multiprocessor.HandleThread]");
}
}
}, stackSize);
t.IsBackground = true;
_threads.Add(t);
}
foreach (var t in _threads) t.Start();
}
public void Append(T t) => _queue.Add(t);
public bool WaitForEmpty(int timeoutInMs)
{
var start = DateTime.UtcNow;
while (Count > 0)
{
if (timeoutInMs > 0)
{
if ((DateTime.UtcNow - start).TotalMilliseconds > timeoutInMs)
{
return false;
}
}
Thread.Sleep(100);
}
return true;
}
public void Dispose()
{
_is_disposed = true;
try
{
_queue.CompleteAdding();
_queue.Dispose();
foreach (var thread in _threads)
{
try
{
thread.Abort();
}
catch { }
}
foreach (var thread in _threads)
{
try
{
thread.Join();
}
catch { }
}
}
catch { }
}
}
}

Powered by TurnKey Linux.