diff --git a/Stone_Red-C-Sharp-Utilities-Test/Program.cs b/Stone_Red-C-Sharp-Utilities-Test/Program.cs index 177bc70..41f8f98 100644 --- a/Stone_Red-C-Sharp-Utilities-Test/Program.cs +++ b/Stone_Red-C-Sharp-Utilities-Test/Program.cs @@ -1,10 +1,9 @@ -using Stone_Red_C_Sharp_Utilities; -using Stone_Red_C_Sharp_Utilities.Logging; +using Stone_Red_C_Sharp_Utilities.Logging; +using Stone_Red_C_Sharp_Utilities.Tasks; using Stone_Red_Utilities.Logging; using System; -using System.Threading; using System.Threading.Tasks; namespace Stone_Red_C_Sharp_Utilities_Test @@ -17,45 +16,58 @@ namespace Stone_Red_C_Sharp_Utilities_Test { FatalConfig = new OutputConfig() { - Color = ConsoleColor.DarkRed, + ConsoleColor = ConsoleColor.DarkRed, LogTarget = LogTarget.Console | LogTarget.DebugConsole | LogTarget.File }, ErrorConfig = new OutputConfig() { - Color = ConsoleColor.Red, + ConsoleColor = ConsoleColor.Red, LogTarget = LogTarget.Console | LogTarget.DebugConsole | LogTarget.File }, WarnConfig = new OutputConfig() { - Color = ConsoleColor.Yellow, + ConsoleColor = ConsoleColor.Yellow, LogTarget = LogTarget.Console | LogTarget.DebugConsole | LogTarget.File }, InfoConfig = new OutputConfig() { - Color = ConsoleColor.White, + ConsoleColor = ConsoleColor.White, LogTarget = LogTarget.Console | LogTarget.DebugConsole | LogTarget.File }, DebugConfig = new OutputConfig() { - Color = ConsoleColor.Gray, + ConsoleColor = ConsoleColor.Gray, LogTarget = LogTarget.Console | LogTarget.DebugConsole }, FormatConfig = new FormatConfig() { - ConsoleFormat = $"{{{LogFormatType.DateTime}:HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Message}}}" + //ConsoleFormat = $"{{{LogFormatType.DateTime}:HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Message}}}" + ConsoleFormat = new LogFormatBuilder().DateTime("HH:mm:ss").Text(" | ").LogSeverity(padding: -5).Text(" | ").Message() } } }; - private static async Task Main() + private static void Main() { TaskQueue taskQueue = new TaskQueue(); - await taskQueue.Enqueue(() => Console.WriteLine("YES1")); - await taskQueue.Enqueue(() => Console.WriteLine("YES2")); - await taskQueue.Enqueue(() => Thread.Sleep(2000)); - await taskQueue.Enqueue(() => Console.WriteLine("YES3")); + _ = taskQueue.Enqueue(CreateTask(0, 1000)).Subscribe((Task t) => logger.LogInfo("Task 0 completed")); + _ = taskQueue.Enqueue(CreateTask(1, 100)).Subscribe((Task t) => logger.LogInfo("Task 1 completed")); + _ = taskQueue.Enqueue(CreateTask(2, 2000)).Subscribe((Task t) => logger.LogInfo("Task 2 completed")); + _ = taskQueue.Enqueue(CreateTask(3, 500)).Subscribe((Task t) => logger.LogInfo("Task 3 completed")); logger.Log("wow", LogSeverity.Info); + + _ = Console.ReadLine(); + } + + private static Task CreateTask(int i, int delay) + { + return new Task(async () => + { + logger.LogInfo($"Start task {i}"); + await Task.Delay(delay); + logger.LogInfo($"End task {i}"); + }); } } } \ No newline at end of file diff --git a/Stone_Red-C-Sharp-Utilities/Logging/LogConfig.cs b/Stone_Red-C-Sharp-Utilities/Logging/LogConfig.cs index e1e743c..32ca1a5 100644 --- a/Stone_Red-C-Sharp-Utilities/Logging/LogConfig.cs +++ b/Stone_Red-C-Sharp-Utilities/Logging/LogConfig.cs @@ -1,8 +1,8 @@ -using Stone_Red_C_Sharp_Utilities.Logging; +using Stone_Red_Utilities.Logging; using System; -namespace Stone_Red_Utilities.Logging +namespace Stone_Red_C_Sharp_Utilities.Logging { /// /// Logging configuration. @@ -48,7 +48,7 @@ namespace Stone_Red_Utilities.Logging /// /// The console color of the log message. /// - public ConsoleColor Color { get; set; } = ConsoleColor.White; + public ConsoleColor ConsoleColor { get; set; } = ConsoleColor.White; /// /// The target for the log message. @@ -69,16 +69,16 @@ namespace Stone_Red_Utilities.Logging /// /// The format for the debug console. /// - public string DebugConsoleFormat { get; set; } = $"{{{LogFormatType.DateTime}:yyyy-MM-dd HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Source},-15}} | {{{LogFormatType.Message}}}"; + public LogFormatBuilder DebugConsoleFormat { get; set; } = $"{{{LogFormatType.DateTime}:yyyy-MM-dd HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Source},-15}} | {{{LogFormatType.Message}}}"; /// /// The format for the console. /// - public string ConsoleFormat { get; set; } = $"{{{LogFormatType.DateTime}:yyyy-MM-dd HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Source},-15}} | {{{LogFormatType.Message}}}"; + public LogFormatBuilder ConsoleFormat { get; set; } = $"{{{LogFormatType.DateTime}:yyyy-MM-dd HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Source},-15}} | {{{LogFormatType.Message}}}"; /// /// The format for the log file. /// - public string FileFormat { get; set; } = $"{{{LogFormatType.DateTime}:yyyy-MM-dd HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Source},-15}} | {{{LogFormatType.Message}}}"; + public LogFormatBuilder FileFormat { get; set; } = $"{{{LogFormatType.DateTime}:yyyy-MM-dd HH:mm:ss}} | {{{LogFormatType.LogSeverity},-5}} | {{{LogFormatType.Source},-15}} | {{{LogFormatType.Message}}}"; } } \ No newline at end of file diff --git a/Stone_Red-C-Sharp-Utilities/Logging/LogFormatBuilder.cs b/Stone_Red-C-Sharp-Utilities/Logging/LogFormatBuilder.cs new file mode 100644 index 0000000..b7d047b --- /dev/null +++ b/Stone_Red-C-Sharp-Utilities/Logging/LogFormatBuilder.cs @@ -0,0 +1,147 @@ +using System.Text; + +namespace Stone_Red_C_Sharp_Utilities.Logging +{ + /// + /// A builder for + /// + public class LogFormatBuilder + { + private readonly StringBuilder stringBuilder = new StringBuilder(); + + /// + /// Creates a new instance. + /// + public LogFormatBuilder() + { + + } + + /// + /// Creates a new instance. + /// + /// The inital format. + public LogFormatBuilder(string value) + { + _ = stringBuilder.Append(value); + } + + /// + /// Appends text to the log format. + /// + /// The text to append. + /// A reference to this instance. + public LogFormatBuilder Text(string value) + { + _ = stringBuilder.Append(value); + return this; + } + + /// + /// Appends the log datie time to the log format. + /// + /// The format to apply. + /// The padding to apply. + /// A reference to this instance. + public LogFormatBuilder DateTime(string format = "", int padding = 0) + { + _ = stringBuilder.Append($"{{{LogFormatType.DateTime},{padding}{GetFormat(format)}}}"); + return this; + } + + /// + /// Appends the log severity to the log format. + /// + /// The format to apply. + /// The padding to apply. + /// A reference to this instance. + public LogFormatBuilder LogSeverity(string format = "", int padding = 0) + { + _ = stringBuilder.Append($"{{{LogFormatType.LogSeverity},{padding}{GetFormat(format)}}}"); + return this; + } + + /// + /// Appends the line number to the log format. + /// + /// The format to apply. + /// The padding to apply. + /// A reference to this instance. + public LogFormatBuilder LineNumber(string format = "", int padding = 0) + { + _ = stringBuilder.Append($"{{{LogFormatType.LineNumber},{padding}{GetFormat(format)}}}"); + return this; + } + + /// + /// Appends the file path to the log format. + /// + /// The format to apply. + /// The padding to apply. + /// A reference to this instance. + public LogFormatBuilder FilePath(string format = "", int padding = 0) + { + _ = stringBuilder.Append($"{{{LogFormatType.FilePath},{padding}{GetFormat(format)}}}"); + return this; + } + + /// + /// Appends the log source to the log format. + /// + /// The format to apply. + /// The padding to apply. + /// A reference to this instance. + public LogFormatBuilder MemberName(string format = "", int padding = 0) + { + _ = stringBuilder.Append($"{{{LogFormatType.MemberName},{padding}{GetFormat(format)}}}"); + return this; + } + + /// + /// Appends the log source to the log format. + /// + /// The format to apply. + /// The padding to apply. + /// A reference to this instance. + public LogFormatBuilder Source(string format = "", int padding = 0) + { + _ = stringBuilder.Append($"{{{LogFormatType.Source},{padding}{GetFormat(format)}}}"); + return this; + } + + /// + /// Appends the log message to the log format. + /// + /// The format to apply. + /// The padding to apply. + /// A reference to this instance. + public LogFormatBuilder Message(string format = "", int padding = 0) + { + _ = stringBuilder.Append($"{{{LogFormatType.Message},{padding}{GetFormat(format)}}}"); + return this; + } + + private string GetFormat(string format) + { + return string.IsNullOrWhiteSpace(format) ? string.Empty : $":{format}"; + } + + /// + /// Converts the /> + /// + /// The to convert. + public static implicit operator string(LogFormatBuilder value) + { + return value.stringBuilder.ToString(); + } + + /// + /// Converts the /> + /// + /// The to convert. + public static implicit operator LogFormatBuilder(string value) + { + return new LogFormatBuilder(value); + } + } +} diff --git a/Stone_Red-C-Sharp-Utilities/Logging/LogFormatType.cs b/Stone_Red-C-Sharp-Utilities/Logging/LogFormatType.cs index 964b960..803941a 100644 --- a/Stone_Red-C-Sharp-Utilities/Logging/LogFormatType.cs +++ b/Stone_Red-C-Sharp-Utilities/Logging/LogFormatType.cs @@ -1,7 +1,7 @@ -namespace Stone_Red_Utilities.Logging +namespace Stone_Red_C_Sharp_Utilities.Logging { /// - /// Specifies the info type of the log message format. + /// Specifies the info type of the log message format. /// public static class LogFormatType { @@ -11,7 +11,7 @@ public const string DateTime = ""; /// - /// The of the log message. + /// The of the log message. /// public const string LogSeverity = ""; diff --git a/Stone_Red-C-Sharp-Utilities/Logging/Logger.cs b/Stone_Red-C-Sharp-Utilities/Logging/Logger.cs new file mode 100644 index 0000000..ddef57e --- /dev/null +++ b/Stone_Red-C-Sharp-Utilities/Logging/Logger.cs @@ -0,0 +1,283 @@ +using Stone_Red_Utilities.Logging; + +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.CompilerServices; + +namespace Stone_Red_C_Sharp_Utilities.Logging +{ + /// + /// Class used for logging + /// + public class Logger + { + /// + /// The logging configuration. + /// + public LogConfig Config { get; set; } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + /// + /// + public void Log(string message, string source, LogSeverity logSeverity, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, source, logSeverity, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + /// + public void Log(string message, LogSeverity logSeverity, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, string.Empty, logSeverity, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + /// + public void LogInfo(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, source, LogSeverity.Info, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + public void LogInfo(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, string.Empty, LogSeverity.Info, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + /// + public void LogWarn(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, source, LogSeverity.Warn, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + public void LogWarn(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, string.Empty, LogSeverity.Warn, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + public void LogError(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, string.Empty, LogSeverity.Error, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + /// + public void LogError(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, source, LogSeverity.Error, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + public void LogFatal(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, string.Empty, LogSeverity.Fatal, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + /// + public void LogFatal(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, source, LogSeverity.Fatal, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + public void LogDebug(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, string.Empty, LogSeverity.Debug, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output + /// + /// + /// + /// + /// + /// + public void LogDebug(string message, string source, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + WriteLog(message, source, LogSeverity.Debug, memberName, sourceFilePath, sourceLineNumber); + } + + /// + /// Log the message to the specified output if the condition is met + /// + /// + /// + /// + /// + /// + /// + /// + public void LogIf(bool condition, string message, string source, LogSeverity logSeverity, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + if (condition) + { + WriteLog(message, source, logSeverity, memberName, sourceFilePath, sourceLineNumber); + } + } + + /// + /// Log the message to the specified output if the condition is met + /// + /// + /// + /// + /// + /// + /// + public void LogIf(bool condition, string message, LogSeverity logSeverity, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) + { + if (condition) + { + WriteLog(message, string.Empty, logSeverity, memberName, sourceFilePath, sourceLineNumber); + } + } + + /// + /// Clears the log file + /// + public void ClearLogFile(LogSeverity logSeverity) + { + OutputConfig outputConfig = GetOutputConfig(logSeverity); + + lock (outputConfig) + { + if (File.Exists(outputConfig.FilePath)) + { + File.WriteAllText(outputConfig.FilePath, string.Empty); + } + } + } + + private void WriteLog(string message, string source, LogSeverity logSeverity, string memberName = "", string sourceFilePath = "", int sourceLineNumber = 0) + { + Config ??= new LogConfig(); + + string consoleOutput = GetFormattedString(Config.FormatConfig.ConsoleFormat, logSeverity, source, message, memberName, sourceFilePath, sourceLineNumber); + string debugOutput = GetFormattedString(Config.FormatConfig.DebugConsoleFormat, logSeverity, source, message, memberName, sourceFilePath, sourceLineNumber); + string fileOutput = GetFormattedString(Config.FormatConfig.FileFormat, logSeverity, source, message, memberName, sourceFilePath, sourceLineNumber); + + OutputConfig outputConfig = GetOutputConfig(logSeverity); + + if ((outputConfig.LogTarget & LogTarget.Console) == LogTarget.Console) + { + ConsoleExt.WriteLine(consoleOutput, outputConfig.ConsoleColor); + } + + if ((outputConfig.LogTarget & LogTarget.DebugConsole) == LogTarget.DebugConsole) + { + Trace.WriteLine(debugOutput); + } + + lock (outputConfig) + { + if ((outputConfig.LogTarget & LogTarget.File) == LogTarget.File) + { + if (!File.Exists(outputConfig.FilePath)) + { + File.Create(outputConfig.FilePath).Close(); + } + + File.AppendAllLines(outputConfig.FilePath, new[] { fileOutput }); + } + } + } + + private OutputConfig GetOutputConfig(LogSeverity logSeverity) + { + return logSeverity switch + { + LogSeverity.Fatal => Config.FatalConfig, + LogSeverity.Error => Config.ErrorConfig, + LogSeverity.Warn => Config.WarnConfig, + LogSeverity.Info => Config.InfoConfig, + _ => Config.DebugConfig + }; + } + + private string GetFormattedString(string format, LogSeverity logSeverity, string source, string message, string memberName, string sourceFilePath, int sourceLineNumber) + { + format = format + .Replace(LogFormatType.DateTime, "0") + .Replace(LogFormatType.LogSeverity, "1") + .Replace(LogFormatType.LineNumber, "2") + .Replace(LogFormatType.FilePath, "3") + .Replace(LogFormatType.MemberName, "4") + .Replace(LogFormatType.Source, "5") + .Replace(LogFormatType.Message, "6"); + + return string.Format(format, DateTime.Now, logSeverity.ToString().ToUpper(), sourceLineNumber, sourceFilePath, memberName, source, message); + } + } +} \ No newline at end of file diff --git a/Stone_Red-C-Sharp-Utilities/Logging/Logging.cs b/Stone_Red-C-Sharp-Utilities/Logging/Logging.cs deleted file mode 100644 index 65edc41..0000000 --- a/Stone_Red-C-Sharp-Utilities/Logging/Logging.cs +++ /dev/null @@ -1,158 +0,0 @@ -using Stone_Red_Utilities.Logging; - -using System; -using System.Diagnostics; -using System.IO; -using System.Runtime.CompilerServices; - -namespace Stone_Red_C_Sharp_Utilities.Logging -{ - /// - /// Class used for logging - /// - public class Logger - { - /// - /// The logging configuration. - /// - public LogConfig Config { get; set; } - - /// - /// Log the message to the specified output - /// - /// - /// - /// - /// - /// - /// - public void Log(string message, string source, LogSeverity logSeverity = LogSeverity.Info, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) - { - WriteLog(message, source, logSeverity, memberName, sourceFilePath, sourceLineNumber); - } - - /// - /// Log the message to the specified output - /// - /// - /// - /// - /// - /// - public void Log(string message, LogSeverity logSeverity = LogSeverity.Info, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) - { - WriteLog(message, string.Empty, logSeverity, memberName, sourceFilePath, sourceLineNumber); - } - - /// - /// Log the message to the specified output if the condition is met - /// - /// - /// - /// - /// - /// - /// - /// - public void LogIf(bool condition, string message, string source, LogSeverity logSeverity = LogSeverity.Info, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) - { - if (condition) - { - WriteLog(message, source, logSeverity, memberName, sourceFilePath, sourceLineNumber); - } - } - - /// - /// Log the message to the specified output if the condition is met - /// - /// - /// - /// - /// - /// - /// - public void LogIf(bool condition, string message, LogSeverity logSeverity = LogSeverity.Info, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) - { - if (condition) - { - WriteLog(message, string.Empty, logSeverity, memberName, sourceFilePath, sourceLineNumber); - } - } - - /// - /// Clears the log file - /// - public void ClearLogFile(LogSeverity logSeverity) - { - OutputConfig outputConfig = GetOutputConfig(logSeverity); - - lock (outputConfig) - { - if (File.Exists(outputConfig.FilePath)) - { - File.WriteAllText(outputConfig.FilePath, string.Empty); - } - } - } - - private void WriteLog(string message, string source, LogSeverity logSeverity, string memberName = "", string sourceFilePath = "", int sourceLineNumber = 0) - { - Config ??= new LogConfig(); - - string consoleOutput = GetFormattedString(Config.FormatConfig.ConsoleFormat, logSeverity, source, message, memberName, sourceFilePath, sourceLineNumber); - string debugOutput = GetFormattedString(Config.FormatConfig.DebugConsoleFormat, logSeverity, source, message, memberName, sourceFilePath, sourceLineNumber); - string fileOutput = GetFormattedString(Config.FormatConfig.FileFormat, logSeverity, source, message, memberName, sourceFilePath, sourceLineNumber); - - OutputConfig outputConfig = GetOutputConfig(logSeverity); - - if ((outputConfig.LogTarget & LogTarget.Console) == LogTarget.Console) - { - ConsoleExt.WriteLine(consoleOutput, outputConfig.Color); - } - - if ((outputConfig.LogTarget & LogTarget.DebugConsole) == LogTarget.DebugConsole) - { - Trace.WriteLine(debugOutput); - } - - lock (outputConfig) - { - if ((outputConfig.LogTarget & LogTarget.File) == LogTarget.File) - { - if (!File.Exists(outputConfig.FilePath)) - { - File.Create(outputConfig.FilePath).Close(); - } - - File.AppendAllLines(outputConfig.FilePath, new[] { fileOutput }); - } - } - } - - private OutputConfig GetOutputConfig(LogSeverity logSeverity) - { - return logSeverity switch - { - LogSeverity.Fatal => Config.FatalConfig, - LogSeverity.Error => Config.ErrorConfig, - LogSeverity.Warn => Config.WarnConfig, - LogSeverity.Info => Config.InfoConfig, - _ => Config.DebugConfig - }; - } - - private string GetFormattedString(string format, LogSeverity logSeverity, string source, string message, string memberName, string sourceFilePath, int sourceLineNumber) - { - format = format - .Replace(LogFormatType.DateTime, "0") - .Replace(LogFormatType.LogSeverity, "1") - .Replace(LogFormatType.LineNumber, "2") - .Replace(LogFormatType.FilePath, "3") - .Replace(LogFormatType.MemberName, "4") - .Replace(LogFormatType.Source, "5") - .Replace(LogFormatType.Message, "6"); - - return string.Format(format, DateTime.Now, logSeverity.ToString().ToUpper(), sourceLineNumber, sourceFilePath, memberName, source, message); - } - } -} \ No newline at end of file diff --git a/Stone_Red-C-Sharp-Utilities/Stone_Red-C-Sharp-Utilities.csproj b/Stone_Red-C-Sharp-Utilities/Stone_Red-C-Sharp-Utilities.csproj index 892d271..d2d68e3 100644 --- a/Stone_Red-C-Sharp-Utilities/Stone_Red-C-Sharp-Utilities.csproj +++ b/Stone_Red-C-Sharp-Utilities/Stone_Red-C-Sharp-Utilities.csproj @@ -33,6 +33,8 @@ + + all diff --git a/Stone_Red-C-Sharp-Utilities/TaskQueue.cs b/Stone_Red-C-Sharp-Utilities/TaskQueue.cs deleted file mode 100644 index fba3276..0000000 --- a/Stone_Red-C-Sharp-Utilities/TaskQueue.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace Stone_Red_C_Sharp_Utilities -{ - /// - /// An queue. - /// - public class TaskQueue - { - private readonly SemaphoreSlim semaphore; - - /// - /// Creates a new - /// - public TaskQueue() - { - semaphore = new SemaphoreSlim(1); - } - - /// - /// Enqueues a . - /// - /// The return type. - /// The code to enqueue. - /// A to await - public async Task Enqueue(Func function) - { - await semaphore.WaitAsync(); - try - { - return await Task.Run(function); - } - finally - { - _ = semaphore.Release(); - } - } - - /// - /// Enqueues an . - /// - /// The code to enqueue. - /// A to await - public async Task Enqueue(Action function) - { - await semaphore.WaitAsync(); - try - { - await Task.Run(function); - } - finally - { - _ = semaphore.Release(); - } - } - } -} \ No newline at end of file diff --git a/Stone_Red-C-Sharp-Utilities/Tasks/BlockingTaskQueue.cs b/Stone_Red-C-Sharp-Utilities/Tasks/BlockingTaskQueue.cs new file mode 100644 index 0000000..40a6bb6 --- /dev/null +++ b/Stone_Red-C-Sharp-Utilities/Tasks/BlockingTaskQueue.cs @@ -0,0 +1,78 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Stone_Red_C_Sharp_Utilities.Tasks +{ + /// + /// An queue. + /// + public class BlockingTaskQueue : ITaskQueue + { + private readonly SemaphoreSlim semaphore; + + /// + /// Creates a new + /// + public BlockingTaskQueue() + { + semaphore = new SemaphoreSlim(1); + } + + /// + public async Task Enqueue(Func function) + { + await semaphore.WaitAsync(); + try + { + return await Task.Run(function); + } + finally + { + _ = semaphore.Release(); + } + } + + /// + public async Task Enqueue(Action function) + { + await semaphore.WaitAsync(); + try + { + await Task.Run(function); + } + finally + { + _ = semaphore.Release(); + } + } + + /// + public async Task Enqueue(Task task) + { + await semaphore.WaitAsync(); + try + { + await task; + } + finally + { + _ = semaphore.Release(); + } + } + + /// + public async Task Enqueue(Task task) + { + await semaphore.WaitAsync(); + try + { + return await task; + } + finally + { + _ = semaphore.Release(); + } + } + } +} \ No newline at end of file diff --git a/Stone_Red-C-Sharp-Utilities/Tasks/ITaskQueue.cs b/Stone_Red-C-Sharp-Utilities/Tasks/ITaskQueue.cs new file mode 100644 index 0000000..b964f0f --- /dev/null +++ b/Stone_Red-C-Sharp-Utilities/Tasks/ITaskQueue.cs @@ -0,0 +1,37 @@ +using System; +using System.Threading.Tasks; + +namespace Stone_Red_C_Sharp_Utilities.Tasks +{ + internal interface ITaskQueue + { + /// + /// Enqueues a . + /// + /// The return type. + /// The code to enqueue. + /// A to await + public Task Enqueue(Func function); + + /// + /// Enqueues an . + /// + /// The code to enqueue. + /// A to await + public Task Enqueue(Action function); + + /// + /// Enqueues an . + /// + /// The code to enqueue. + /// A to await + public Task Enqueue(Task task); + + /// + /// Enqueues an . + /// + /// The code to enqueue. + /// A to await + public Task Enqueue(Task task); + } +} diff --git a/Stone_Red-C-Sharp-Utilities/Tasks/TaskQueue.cs b/Stone_Red-C-Sharp-Utilities/Tasks/TaskQueue.cs new file mode 100644 index 0000000..5a3e2b6 --- /dev/null +++ b/Stone_Red-C-Sharp-Utilities/Tasks/TaskQueue.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Concurrent; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Threading.Tasks; + +namespace Stone_Red_C_Sharp_Utilities.Tasks +{ + /// + /// An queue. + /// + public class TaskQueue + { + private readonly ConcurrentQueue<(Task Task, Action Callback)> tasks = new ConcurrentQueue<(Task Task, Action Callback)>(); + private bool processing = false; + + /// + public IObservable> Enqueue(Func function) + { + Subject> subject = new Subject>(); + Task task = new Task(function); + + tasks.Enqueue((task, () => subject.OnNext(task))); + + ProcessTasks(); + + return subject.AsObservable(); + } + + /// + public IObservable Enqueue(Action function) + { + Subject subject = new Subject(); + Task task = new Task(function); + + tasks.Enqueue((task, () => subject.OnNext(task))); + + ProcessTasks(); + + return subject.AsObservable(); + } + + /// + public IObservable Enqueue(Task task) + { + Subject subject = new Subject(); + + tasks.Enqueue((task, () => subject.OnNext(task))); + + ProcessTasks(); + + return subject.AsObservable(); + } + + /// + public IObservable> Enqueue(Task task) + { + Subject> subject = new Subject>(); + + tasks.Enqueue((task, () => subject.OnNext(task))); + + ProcessTasks(); + + return subject.AsObservable(); + } + + private async void ProcessTasks() + { + if (processing) + { + return; + } + + processing = true; + + while (tasks.TryDequeue(out (Task Task, Action Callback) container)) + { + if (container.Task.Status == TaskStatus.Created) + { + container.Task.Start(); + } + + await container.Task; + container.Callback?.Invoke(); + } + } + } +} \ No newline at end of file