diff --git a/Entities/ScheduledTask.cs b/Entities/ScheduledTask.cs
new file mode 100644
index 0000000..7c78eb6
--- /dev/null
+++ b/Entities/ScheduledTask.cs
@@ -0,0 +1,35 @@
+namespace Xorog.UniversalExtensions.Entities;
+
+public class ScheduledTask
+{
+ internal ScheduledTask()
+ {
+ this.Uid = Guid.NewGuid().ToString();
+ }
+
+ ///
+ /// The unique identifier of this task.
+ ///
+ public string Uid { get; internal set; }
+
+ ///
+ /// The custom data asscociated with this task.
+ ///
+ public object? CustomData { get; internal set; }
+
+ ///
+ /// The time this task will run.
+ ///
+ public DateTime? RunTime { get; internal set; }
+
+ ///
+ /// The to prematurely dequeue this task.
+ ///
+ internal CancellationTokenSource? TokenSource { get; set; } = new();
+
+ ///
+ /// Delete this task.
+ ///
+ public void Delete() =>
+ ScheduledTaskExtensions.DeleteScheduledTask(Uid);
+}
diff --git a/EventArgs/ScheduledTaskStartedEventArgs.cs b/EventArgs/ScheduledTaskStartedEventArgs.cs
new file mode 100644
index 0000000..f8e3471
--- /dev/null
+++ b/EventArgs/ScheduledTaskStartedEventArgs.cs
@@ -0,0 +1,22 @@
+using Xorog.UniversalExtensions.Entities;
+
+namespace Xorog.UniversalExtensions.EventArgs;
+
+public class ScheduledTaskStartedEventArgs : System.EventArgs
+{
+ internal ScheduledTaskStartedEventArgs(ScheduledTask details, Task task)
+ {
+ this.Details = details;
+ this.Task = task;
+ }
+
+ ///
+ /// The details of this scheduled task.
+ ///
+ public ScheduledTask Details { get; internal set; }
+
+ ///
+ /// The task that was executed.
+ ///
+ public Task Task { get; internal set; }
+}
diff --git a/Extensions/ScheduledTaskExtensions.cs b/Extensions/ScheduledTaskExtensions.cs
index 74f675c..a9473d9 100644
--- a/Extensions/ScheduledTaskExtensions.cs
+++ b/Extensions/ScheduledTaskExtensions.cs
@@ -1,52 +1,61 @@
-namespace Xorog.UniversalExtensions;
+using Xorog.UniversalExtensions.Entities;
+using Xorog.UniversalExtensions.EventArgs;
+
+namespace Xorog.UniversalExtensions;
public static class ScheduledTaskExtensions
{
+ ///
+ /// Fired when a log message has been sent.
+ ///
+ public static event EventHandler? TaskStarted;
+
///
/// Create a scheduled task
///
- /// The task to run
+ /// The task to run
/// The time to run the task
/// Any custom data you wish to provide.
/// An unique identifier of the task
- public static string CreateScheduledTask(this Task task, DateTime runTime, object? customData = null)
+ public static string CreateScheduledTask(this Func taskFunc, DateTime runTime, object? customData = null)
{
- if (task.Status != TaskStatus.Created)
- throw new InvalidOperationException("The task is already being executed or has been scheduled for execution.")
- .AttachData("Task", task)
- .AttachData("RunTime", runTime)
- .AttachData("CustomData", customData);
-
string UID = Guid.NewGuid().ToString();
CancellationTokenSource CancellationToken = new CancellationTokenSource();
if (Math.Ceiling(runTime.GetTimespanUntil().TotalMilliseconds) < 0)
runTime = DateTime.UtcNow.AddSeconds(1);
+ var scheduledTask = new ScheduledTask
+ {
+ Uid = UID,
+ RunTime = runTime,
+ TokenSource = CancellationToken,
+ CustomData = customData,
+ };
+
_ = LongDelay(runTime.GetTimespanUntil(), CancellationToken).ContinueWith(x =>
{
- lock (RegisteredScheduledTasks)
+ lock (InternalScheduler.RegisteredScheduledTasks)
{
- RegisteredScheduledTasks.Remove(UID);
+ InternalScheduler.RegisteredScheduledTasks.Remove(UID);
}
_logger?.LogDebug("Running scheduled task with UID '{UID}'", UID, runTime.GetTimespanUntil().GetHumanReadable());
if (x.IsCompletedSuccessfully)
- task.Start();
+ {
+ var task = Task.Run(taskFunc);
+ _ = Task.Run(() =>
+ {
+ ScheduledTaskExtensions.TaskStarted?.Invoke(null, new ScheduledTaskStartedEventArgs(scheduledTask, task));
+ });
+ }
});
- lock (RegisteredScheduledTasks)
+ lock (InternalScheduler.RegisteredScheduledTasks)
{
_logger?.LogDebug("Creating scheduled task with UID '{UID}' running in {RunTime}", UID, runTime.GetTimespanUntil().GetHumanReadable());
-
- RegisteredScheduledTasks.Add(UID, new ScheduledTask
- {
- Uid = UID,
- RunTime = runTime,
- TokenSource = CancellationToken,
- CustomData = customData,
- });
+ InternalScheduler.RegisteredScheduledTasks.Add(UID, scheduledTask);
}
return UID;
}
@@ -60,18 +69,18 @@ public static class ScheduledTaskExtensions
/// Throws if the task hasn't been found or if an internal error occurred
public static void DeleteScheduledTask(string UID)
{
- if (!RegisteredScheduledTasks.ContainsKey(UID))
+ if (!InternalScheduler.RegisteredScheduledTasks.ContainsKey(UID))
throw new KeyNotFoundException($"No scheduled task has been found with UID '{UID}'");
- if (RegisteredScheduledTasks[UID].TokenSource is null)
+ if (InternalScheduler.RegisteredScheduledTasks[UID].TokenSource is null)
throw new Exception($"Internal: There is no token source registered the specified task.");
_logger?.LogDebug("Deleting scheduled task with UID '{UID}'", UID);
- lock (RegisteredScheduledTasks)
+ lock (InternalScheduler.RegisteredScheduledTasks)
{
- RegisteredScheduledTasks[UID].TokenSource?.Cancel();
- RegisteredScheduledTasks.Remove(UID);
+ InternalScheduler.RegisteredScheduledTasks[UID].TokenSource?.Cancel();
+ InternalScheduler.RegisteredScheduledTasks.Remove(UID);
}
return;
}
@@ -83,7 +92,7 @@ public static class ScheduledTaskExtensions
///
/// A list of all registered tasks
public static IReadOnlyList? GetScheduledTasks()
- => RegisteredScheduledTasks.Select(x => x.Value).ToList().AsReadOnly();
+ => InternalScheduler.RegisteredScheduledTasks.Select(x => x.Value).ToList().AsReadOnly();
///
/// Gets a specific task
@@ -92,7 +101,7 @@ public static class ScheduledTaskExtensions
/// The task
/// Throws if the task has not been found
public static ScheduledTask GetScheduledTask(string UID)
- => RegisteredScheduledTasks[UID];
+ => InternalScheduler.RegisteredScheduledTasks[UID];
internal static async Task LongDelay(TimeSpan delay, CancellationTokenSource token)
{
diff --git a/Global.cs b/Global.cs
index 05154bc..1d92821 100644
--- a/Global.cs
+++ b/Global.cs
@@ -9,6 +9,4 @@ global using System.Drawing;
global using Microsoft.Extensions.Logging;
global using Xorog.UniversalExtensions.Enums;
-global using static Xorog.UniversalExtensions.Internal;
-global using static Xorog.UniversalExtensions.InternalSheduler;
global using static Xorog.UniversalExtensions.Log;
\ No newline at end of file
diff --git a/Internal/Internal.cs b/Internal/Internal.cs
index 69b4697..da5267d 100644
--- a/Internal/Internal.cs
+++ b/Internal/Internal.cs
@@ -1,4 +1,6 @@
-namespace Xorog.UniversalExtensions;
+using Xorog.UniversalExtensions.Entities;
+
+namespace Xorog.UniversalExtensions;
internal static class Internal
{
@@ -79,43 +81,9 @@ internal static class Internal
}
}
-public class InternalSheduler
+internal class InternalScheduler
{
public static Dictionary RegisteredScheduledTasks { get; internal set; } = new Dictionary();
-
- public class ScheduledTask
- {
- public ScheduledTask()
- {
- this.Uid = Guid.NewGuid().ToString();
- }
-
- ///
- /// The unique identifier of this task.
- ///
- public string Uid { get; internal set; }
-
- ///
- /// The custom data asscociated with this task.
- ///
- public object? CustomData { get; internal set; }
-
- ///
- /// The time this task will run.
- ///
- public DateTime? RunTime { get; internal set; }
-
- ///
- /// The to prematurely dequeue this task.
- ///
- internal CancellationTokenSource? TokenSource { get; set; } = new();
-
- ///
- /// Delete this task.
- ///
- public void Delete() =>
- ScheduledTaskExtensions.DeleteScheduledTask(Uid);
- }
}
public class HumanReadableTimeFormatConfig