Files
RAGECOOP-V/Core/Worker.cs

90 lines
2.6 KiB
C#
Raw Normal View History

2022-06-27 13:30:35 +08:00
using System;
using System.Collections.Concurrent;
2022-09-08 12:41:56 -07:00
using System.Threading;
2022-06-27 13:30:35 +08:00
namespace RageCoop.Core
{
2022-07-01 14:39:43 +08:00
/// <summary>
2022-10-23 19:02:39 +08:00
/// A worker that constantly execute jobs in a background thread.
2022-07-01 14:39:43 +08:00
/// </summary>
2022-09-08 12:41:56 -07:00
public class Worker : IDisposable
2022-06-27 13:30:35 +08:00
{
2022-09-08 12:41:56 -07:00
private readonly SemaphoreSlim _semaphoreSlim;
private readonly Thread _workerThread;
2022-10-23 19:02:39 +08:00
private readonly ConcurrentQueue<Action> Jobs = new ConcurrentQueue<Action>();
private bool _stopping;
internal Worker(string name, Logger logger, int maxJobs = int.MaxValue)
{
Name = name;
_semaphoreSlim = new SemaphoreSlim(0, maxJobs);
_workerThread = new Thread(() =>
{
while (!_stopping)
{
IsBusy = false;
_semaphoreSlim.Wait();
if (Jobs.TryDequeue(out var job))
{
IsBusy = true;
try
{
job.Invoke();
}
catch (Exception ex)
{
logger.Error("Error occurred when executing queued job:");
logger.Error(ex);
}
}
else
{
throw new InvalidOperationException("Hmm... that's unexpected.");
}
}
IsBusy = false;
});
_workerThread.Start();
}
2022-07-01 14:39:43 +08:00
/// <summary>
2022-10-23 19:02:39 +08:00
/// Name of the worker
2022-07-01 14:39:43 +08:00
/// </summary>
2022-06-27 13:30:35 +08:00
public string Name { get; set; }
2022-10-23 19:02:39 +08:00
2022-07-01 14:39:43 +08:00
/// <summary>
2022-10-23 19:02:39 +08:00
/// Whether this worker is busy executing job(s).
2022-07-01 14:39:43 +08:00
/// </summary>
2022-09-08 12:41:56 -07:00
public bool IsBusy { get; private set; }
2022-10-23 19:02:39 +08:00
/// <summary>
/// Finish current job and stop the worker.
/// </summary>
public void Dispose()
2022-06-27 13:30:35 +08:00
{
2022-10-23 19:02:39 +08:00
Stop();
_semaphoreSlim.Dispose();
2022-06-27 13:30:35 +08:00
}
2022-10-23 19:02:39 +08:00
2022-07-01 14:39:43 +08:00
/// <summary>
2022-10-23 19:02:39 +08:00
/// Queue a job to be executed
2022-07-01 14:39:43 +08:00
/// </summary>
/// <param name="work"></param>
2022-06-30 09:28:13 +08:00
public void QueueJob(Action work)
2022-06-27 13:30:35 +08:00
{
Jobs.Enqueue(work);
_semaphoreSlim.Release();
}
2022-10-23 19:02:39 +08:00
2022-07-01 14:39:43 +08:00
/// <summary>
2022-10-23 19:02:39 +08:00
/// Finish current job and stop the worker.
2022-07-01 14:39:43 +08:00
/// </summary>
2022-06-27 13:30:35 +08:00
public void Stop()
{
2022-09-08 12:41:56 -07:00
_stopping = true;
2022-06-30 09:28:13 +08:00
QueueJob(() => { });
2022-10-23 19:02:39 +08:00
if (_workerThread.IsAlive) _workerThread.Join();
2022-06-27 13:30:35 +08:00
}
}
2022-10-23 19:02:39 +08:00
}