新增日志输出模式,规范写法
parent
b74e1634ee
commit
bc6b4e5ab0
|
@ -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,
|
||||||
}
|
}
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue