新增日志输出模式,规范写法

master
Cal 2024-12-09 10:40:33 +08:00
parent b74e1634ee
commit bc6b4e5ab0
2 changed files with 65 additions and 30 deletions

View File

@ -4,11 +4,13 @@ using System.Runtime.InteropServices;
unsafe unsafe
{ {
Console.WriteLine(1); Console.WriteLine(1);
SetLogImmediately(true); SetLogOutputMode(LogMode.Manual);
SetLogInfo(& LogInfo); SetLogInfo(& LogInfo);
SetLogError(& LogError); SetLogError(& LogError);
TimeProvider.System.CreateTimer(Callback, null, TimeSpan.FromMilliseconds(16), TimeSpan.FromMilliseconds(16)); //Manual 才需要这个手动调用
//TimeProvider.System.CreateTimer(Callback, null, TimeSpan.FromMilliseconds(16), TimeSpan.FromMilliseconds(16));
void Callback(object? state) void Callback(object? state)
{ {
Tick(); Tick();
@ -20,9 +22,9 @@ unsafe
(char*)Unsafe.AsPointer(ref Unsafe.AsRef(in "C:\\A".GetPinnableReference())), (char*)Unsafe.AsPointer(ref Unsafe.AsRef(in "C:\\A".GetPinnableReference())),
(char*)Unsafe.AsPointer(ref Unsafe.AsRef(in "C:\\B".GetPinnableReference()))); (char*)Unsafe.AsPointer(ref Unsafe.AsRef(in "C:\\B".GetPinnableReference())));
Console.ReadKey(); Console.ReadKey();
[DllImport("FileUtilsCs.dll", EntryPoint = "SetLogImmediately")] [DllImport("FileUtilsCs.dll", EntryPoint = "SetLogOutputMode")]
static extern void SetLogImmediately(bool value); static extern void SetLogOutputMode([MarshalAs(UnmanagedType.I4)]LogMode value);
[DllImport("FileUtilsCs.dll", EntryPoint = "TestLog")] [DllImport("FileUtilsCs.dll", EntryPoint = "TestLog")]
static extern void TestLog(); static extern void TestLog();
@ -47,4 +49,15 @@ unsafe
var addrOfPinnedObject = new string((char*)obj); var addrOfPinnedObject = new string((char*)obj);
System.Console.WriteLine(addrOfPinnedObject); System.Console.WriteLine(addrOfPinnedObject);
} }
}
enum LogMode
{
//自动
Auto,
//立即输出
Immediate,
//手动Tick
Manual,
} }

View File

@ -1,41 +1,64 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.ComponentModel;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace FileUtilsCs; namespace FileUtilsCs;
public class EntryPoints enum LogMode
{
//自动
Auto,
//立即输出
Immediate,
//手动Tick
Manual,
}
public static class EntryPoints
{ {
internal static Action<string>? logInfoAction; internal static Action<string>? logInfoAction;
internal static Action<string>? logErrorAction; internal static Action<string>? logErrorAction;
internal static bool logImmediately = false; internal static LogMode mode = LogMode.Auto;
static ConcurrentQueue<string> _logQueue = new ConcurrentQueue<string>(); static ConcurrentQueue<string> _logInfoQueue = new ConcurrentQueue<string>();
static ConcurrentQueue<string> _logErrorQueue = new ConcurrentQueue<string>(); static ConcurrentQueue<string> _logErrorQueue = new ConcurrentQueue<string>();
[UnmanagedCallersOnly(EntryPoint = "Tick")] static EntryPoints()
static void Tick() {
TimeProvider.System.CreateTimer(LogCallBack, null, TimeSpan.FromMilliseconds(0), TimeSpan.FromMilliseconds(16));
}
private static void LogCallBack(object? state)
{
if (mode == LogMode.Auto)
TickLog();
}
private static void TickLog()
{ {
if (logImmediately)
return;
if (_logErrorQueue.TryDequeue(out var error)) if (_logErrorQueue.TryDequeue(out var error))
{ {
logErrorAction?.Invoke(error); logErrorAction?.Invoke(error);
} }
if (_logInfoQueue.TryDequeue(out var message))
_logErrorQueue.Clear();
if (_logQueue.TryDequeue(out var message))
{ {
logInfoAction?.Invoke(message); logInfoAction?.Invoke(message);
} }
}
_logQueue.Clear(); [UnmanagedCallersOnly(EntryPoint = "Tick")]
static void Tick()
{
if (mode != LogMode.Manual)
return;
TickLog();
} }
public static void LogError(string message) public static void LogError(string message)
{ {
if (logImmediately) if (mode == LogMode.Immediate)
logErrorAction?.Invoke(message); logErrorAction?.Invoke(message);
else else
_logErrorQueue.Enqueue(message); _logErrorQueue.Enqueue(message);
@ -43,22 +66,22 @@ public class EntryPoints
public static void Log(string message) public static void Log(string message)
{ {
if (logImmediately) if (mode == LogMode.Immediate)
logInfoAction?.Invoke(message); logInfoAction?.Invoke(message);
else else
_logQueue.Enqueue(message); _logInfoQueue.Enqueue(message);
} }
/// <summary> /// <summary>
/// 立即输出日志 /// 设置日志输出类型
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="mode"></param>
[UnmanagedCallersOnly(EntryPoint = "SetLogImmediately")] [UnmanagedCallersOnly(EntryPoint = "SetLogOutputMode")]
public static void SetLogImmediately(bool value) public static void SetLogOutputMode(int mode = 0)
{ {
logImmediately = value; EntryPoints.mode = (LogMode)mode;
} }
[UnmanagedCallersOnly(EntryPoint = "SetLogInfo")] [UnmanagedCallersOnly(EntryPoint = "SetLogInfo")]
public static unsafe void SetLogInfo(delegate* managed<nint, void> logAction) public static unsafe void SetLogInfo(delegate* managed<nint, void> logAction)
{ {
@ -106,9 +129,9 @@ public class EntryPoints
try try
{ {
if (isRoot && !Directory.Exists(srcRootPath)) if (isRoot && !Directory.Exists(srcRootPath))
throw new Exception($"srcRootPath : {srcRootPath} not exists!"); throw new Win32Exception($"srcRootPath : {srcRootPath} not exists!");
if (isRoot && !Directory.Exists(destRootPath)) if (isRoot && !Directory.Exists(destRootPath))
throw new Exception($"srcRootPath : {destRootPath} not exists!"); throw new Win32Exception($"srcRootPath : {destRootPath} not exists!");
if (Path.GetFullPath(srcRootPath) == Path.GetFullPath(destRootPath)) if (Path.GetFullPath(srcRootPath) == Path.GetFullPath(destRootPath))
return; return;
srcRootPath = srcRootPath[srcRootPath.Length - 1] != Path.DirectorySeparatorChar ? srcRootPath + Path.DirectorySeparatorChar : srcRootPath; srcRootPath = srcRootPath[srcRootPath.Length - 1] != Path.DirectorySeparatorChar ? srcRootPath + Path.DirectorySeparatorChar : srcRootPath;
@ -128,8 +151,7 @@ public class EntryPoints
var destDirectoryInfo = new FileInfo(destFileFullName).Directory; var destDirectoryInfo = new FileInfo(destFileFullName).Directory;
if (destDirectoryInfo == null) if (destDirectoryInfo == null)
{ {
LogError($"destDirectoryInfo is null where path is :{destFileFullName}"); throw new IOException($"destDirectoryInfo is null where path is :{destFileFullName}");
return;
} }
if (!destDirectoryInfo.Exists) if (!destDirectoryInfo.Exists)