浏览代码

增加获取指定进程的CPU和内存使用统计

懒得勤快 10 月之前
父节点
当前提交
7ca683832d

+ 21 - 32
Masuit.Tools.Abstractions/Extensions/BaseType/ObjectExtensions.cs

@@ -9,15 +9,12 @@ using Masuit.Tools.Reflection;
 using Newtonsoft.Json.Linq;
 using Newtonsoft.Json.Linq;
 
 
 #if NETSTANDARD2_1_OR_GREATER
 #if NETSTANDARD2_1_OR_GREATER
-
 using System.Text.Json;
 using System.Text.Json;
 using Masuit.Tools.Systems;
 using Masuit.Tools.Systems;
 using JsonSerializer = System.Text.Json.JsonSerializer;
 using JsonSerializer = System.Text.Json.JsonSerializer;
-
 #endif
 #endif
 
 
 #if NET5_0_OR_GREATER
 #if NET5_0_OR_GREATER
-
 using System.Text.Json;
 using System.Text.Json;
 using Masuit.Tools.Systems;
 using Masuit.Tools.Systems;
 using JsonSerializer = System.Text.Json.JsonSerializer;
 using JsonSerializer = System.Text.Json.JsonSerializer;
@@ -54,6 +51,7 @@ public static class ObjectExtensions
     };
     };
 
 
 #endif
 #endif
+
     /// <summary>
     /// <summary>
     /// 是否是基本数据类型
     /// 是否是基本数据类型
     /// </summary>
     /// </summary>
@@ -147,9 +145,7 @@ public static class ObjectExtensions
     /// <returns></returns>
     /// <returns></returns>
     public static object DeepClone(this object originalObject, bool useJson = false)
     public static object DeepClone(this object originalObject, bool useJson = false)
     {
     {
-        return useJson
-            ? InternalJsonCopy(originalObject)
-            : InternalCopy(originalObject, new Dictionary<object, object>(new ReferenceEqualityComparer()));
+        return useJson ? InternalJsonCopy(originalObject) : InternalCopy(originalObject, new Dictionary<object, object>(new ReferenceEqualityComparer()));
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -258,8 +254,7 @@ public static class ObjectExtensions
     /// <typeparam name="T"></typeparam>
     /// <typeparam name="T"></typeparam>
     /// <param name="value"></param>
     /// <param name="value"></param>
     /// <returns></returns>
     /// <returns></returns>
-    public static bool IsNullOrEmpty<T>(this T value)
-        where T : class
+    public static bool IsNullOrEmpty<T>(this T value) where T : class
     {
     {
         return value switch
         return value switch
         {
         {
@@ -303,31 +298,30 @@ public static class ObjectExtensions
 
 
     #region System.Text.Json
     #region System.Text.Json
 
 
-    #if NET5_0_OR_GREATER
-    
+#if NET5_0_OR_GREATER
+
     /// <summary>
     /// <summary>
     /// 转换成json字符串
     /// 转换成json字符串
     /// </summary>
     /// </summary>
     /// <param name="obj"></param>
     /// <param name="obj"></param>
     /// <param name="setting"></param>
     /// <param name="setting"></param>
     /// <returns></returns>
     /// <returns></returns>
-    public static string ToJson(this object obj, JsonSerializerOptions setting = null)
+    public static string ToJsonString(this object obj, JsonSerializerOptions setting)
     {
     {
         if (obj == null) return string.Empty;
         if (obj == null) return string.Empty;
         setting ??= DefaultJsonSerializerOptions;
         setting ??= DefaultJsonSerializerOptions;
-        return JsonSerializer.Serialize(obj,setting);
+        return JsonSerializer.Serialize(obj, setting);
     }
     }
-    
+
     /// <summary>
     /// <summary>
     /// 转换成json字符串并忽略Null值
     /// 转换成json字符串并忽略Null值
     /// </summary>
     /// </summary>
     /// <param name="obj"></param>
     /// <param name="obj"></param>
-    /// <param name="setting"></param>
     /// <returns></returns>
     /// <returns></returns>
     public static string ToJsonIgnoreNull(this object obj)
     public static string ToJsonIgnoreNull(this object obj)
     {
     {
         if (obj == null) return string.Empty;
         if (obj == null) return string.Empty;
-        return JsonSerializer.Serialize(obj,IgnoreNullJsonSerializerOptions);
+        return JsonSerializer.Serialize(obj, IgnoreNullJsonSerializerOptions);
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -336,15 +330,14 @@ public static class ObjectExtensions
     /// <param name="json"></param>
     /// <param name="json"></param>
     /// <param name="settings"></param>
     /// <param name="settings"></param>
     /// <returns></returns>
     /// <returns></returns>
-    public static T ToObject<T>(this string json, JsonSerializerOptions settings = null)
+    public static T FromJson<T>(this string json, JsonSerializerOptions settings)
     {
     {
         return string.IsNullOrEmpty(json) ? default : JsonSerializer.Deserialize<T>(json, settings);
         return string.IsNullOrEmpty(json) ? default : JsonSerializer.Deserialize<T>(json, settings);
     }
     }
 
 
-    #endif
-
-    #endregion
+#endif
 
 
+    #endregion System.Text.Json
 
 
     /// <summary>
     /// <summary>
     /// 链式操作
     /// 链式操作
@@ -373,6 +366,7 @@ public static class ObjectExtensions
                 {
                 {
                     dictionary.Add(e.Key.ToString(), e.Value);
                     dictionary.Add(e.Key.ToString(), e.Value);
                 }
                 }
+
                 return dictionary;
                 return dictionary;
             }
             }
 
 
@@ -425,13 +419,9 @@ public static class ObjectExtensions
     /// <param name="others"></param>
     /// <param name="others"></param>
     public static T Merge<T>(this T a, T b, params T[] others) where T : class
     public static T Merge<T>(this T a, T b, params T[] others) where T : class
     {
     {
-        foreach (var item in new[] { b }.Concat(others))
+        foreach (var p in new[] { b }.Concat(others).Select(item => item.ToDictionary()).SelectMany(dic => dic.Where(p => a.GetProperty(p.Key).IsDefaultValue())))
         {
         {
-            var dic = item.ToDictionary();
-            foreach (var p in dic.Where(p => a.GetProperty(p.Key).IsDefaultValue()))
-            {
-                a.SetProperty(p.Key, p.Value);
-            }
+            a.SetProperty(p.Key, p.Value);
         }
         }
 
 
         return a;
         return a;
@@ -453,13 +443,9 @@ public static class ObjectExtensions
                 return list[0];
                 return list[0];
         }
         }
 
 
-        foreach (var item in list.Skip(1))
+        foreach (var p in list.Skip(1).Select(item => item.ToDictionary()).SelectMany(dic => dic.Where(p => list[0].GetProperty(p.Key).IsDefaultValue())))
         {
         {
-            var dic = item.ToDictionary();
-            foreach (var p in dic.Where(p => list[0].GetProperty(p.Key).IsDefaultValue()))
-            {
-                list[0].SetProperty(p.Key, p.Value);
-            }
+            list[0].SetProperty(p.Key, p.Value);
         }
         }
 
 
         return list[0];
         return list[0];
@@ -505,6 +491,7 @@ internal static class ArrayExtensions
             {
             {
                 _maxLengths[i] = array.GetLength(i) - 1;
                 _maxLengths[i] = array.GetLength(i) - 1;
             }
             }
+
             Position = new int[array.Rank];
             Position = new int[array.Rank];
         }
         }
 
 
@@ -519,10 +506,12 @@ internal static class ArrayExtensions
                     {
                     {
                         Position[j] = 0;
                         Position[j] = 0;
                     }
                     }
+
                     return true;
                     return true;
                 }
                 }
             }
             }
+
             return false;
             return false;
         }
         }
     }
     }
-}
+}

+ 32 - 17
Masuit.Tools.Abstractions/Hardware/SystemInfo.cs

@@ -272,6 +272,16 @@ namespace Masuit.Tools.Hardware
             return null;
             return null;
         }
         }
 
 
+        /// <summary>
+        /// 获取进程的CPU使用率
+        /// </summary>
+        /// <returns></returns>
+        public static float GetProcessCpuUsage(int pid)
+        {
+            using var process = Process.GetProcessById(pid);
+            return GetProcessCpuUsage(process);
+        }
+
         /// <summary>
         /// <summary>
         /// 获取进程的CPU使用率
         /// 获取进程的CPU使用率
         /// </summary>
         /// </summary>
@@ -279,8 +289,6 @@ namespace Masuit.Tools.Hardware
         /// <returns></returns>
         /// <returns></returns>
         public static IEnumerable<(Process process, float usage)> GetProcessCpuUsage(string name)
         public static IEnumerable<(Process process, float usage)> GetProcessCpuUsage(string name)
         {
         {
-            if (!IsWinPlatform) return [];
-
             var processes = Process.GetProcessesByName(name);
             var processes = Process.GetProcessesByName(name);
             return GetProcessCpuUsage(processes);
             return GetProcessCpuUsage(processes);
         }
         }
@@ -292,8 +300,7 @@ namespace Masuit.Tools.Hardware
         /// <returns></returns>
         /// <returns></returns>
         public static IEnumerable<(Process process, float usage)> GetProcessCpuUsage(this Process[] processes)
         public static IEnumerable<(Process process, float usage)> GetProcessCpuUsage(this Process[] processes)
         {
         {
-            if (!IsWinPlatform) return [];
-            return processes.Select(GetProcessCpuUsage);
+            return processes.Select(p => (p, GetProcessCpuUsage(p)));
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -301,19 +308,19 @@ namespace Masuit.Tools.Hardware
         /// </summary>
         /// </summary>
         /// <param name="process"></param>
         /// <param name="process"></param>
         /// <returns></returns>
         /// <returns></returns>
-        public static (Process process, float usage) GetProcessCpuUsage(this Process process)
+        public static float GetProcessCpuUsage(this Process process)
         {
         {
-            if (!IsWinPlatform) return (process, 0);
+            if (!IsWinPlatform) return 0;
             string instance = GetInstanceName(process);
             string instance = GetInstanceName(process);
             if (instance != null)
             if (instance != null)
             {
             {
-                var cpuCounter = Counters.GetOrAdd("Processor Time" + instance, new PerformanceCounter("Process", "% Processor Time", instance));
+                var cpuCounter = Counters.GetOrAdd("Processor Time" + instance, () => new PerformanceCounter("Process", "% Processor Time", instance));
                 cpuCounter.NextValue();
                 cpuCounter.NextValue();
                 Thread.Sleep(200); //等200ms(是测出能换取下个样本的最小时间间隔),让后系统获取下一个样本,因为第一个样本无效
                 Thread.Sleep(200); //等200ms(是测出能换取下个样本的最小时间间隔),让后系统获取下一个样本,因为第一个样本无效
                 var usage = cpuCounter.NextValue() / Environment.ProcessorCount;
                 var usage = cpuCounter.NextValue() / Environment.ProcessorCount;
-                return (process, usage);
+                return usage;
             }
             }
-            return (process, 0);
+            return 0;
         }
         }
 
 
         #endregion CPU相关
         #endregion CPU相关
@@ -476,6 +483,16 @@ namespace Masuit.Tools.Hardware
             return GetTotalPhysicalMemory() - GetFreePhysicalMemory();
             return GetTotalPhysicalMemory() - GetFreePhysicalMemory();
         }
         }
 
 
+        /// <summary>
+        /// 获取进程的内存使用量,单位:MB
+        /// </summary>
+        /// <returns></returns>
+        public static float GetProcessMemory(int pid)
+        {
+            using var process = Process.GetProcessById(pid);
+            return GetProcessMemory(process);
+        }
+
         /// <summary>
         /// <summary>
         /// 获取进程的内存使用量,单位:MB
         /// 获取进程的内存使用量,单位:MB
         /// </summary>
         /// </summary>
@@ -483,7 +500,6 @@ namespace Masuit.Tools.Hardware
         /// <returns></returns>
         /// <returns></returns>
         public static IEnumerable<(Process process, float usage)> GetProcessMemory(string name)
         public static IEnumerable<(Process process, float usage)> GetProcessMemory(string name)
         {
         {
-            if (!IsWinPlatform) return [];
             var processes = Process.GetProcessesByName(name);
             var processes = Process.GetProcessesByName(name);
             return GetProcessMemory(processes);
             return GetProcessMemory(processes);
         }
         }
@@ -495,8 +511,7 @@ namespace Masuit.Tools.Hardware
         /// <returns></returns>
         /// <returns></returns>
         public static IEnumerable<(Process process, float usage)> GetProcessMemory(this Process[] processes)
         public static IEnumerable<(Process process, float usage)> GetProcessMemory(this Process[] processes)
         {
         {
-            if (!IsWinPlatform) return [];
-            return processes.Select(GetProcessMemory);
+            return processes.Select(p => (p, GetProcessMemory(p)));
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -504,17 +519,17 @@ namespace Masuit.Tools.Hardware
         /// </summary>
         /// </summary>
         /// <param name="process"></param>
         /// <param name="process"></param>
         /// <returns></returns>
         /// <returns></returns>
-        public static (Process process, float usage) GetProcessMemory(this Process process)
+        public static float GetProcessMemory(this Process process)
         {
         {
-            if (!IsWinPlatform) return (process, 0);
+            if (!IsWinPlatform) return 0;
             string instance = GetInstanceName(process);
             string instance = GetInstanceName(process);
             if (instance != null)
             if (instance != null)
             {
             {
-                var ramCounter = Counters.GetOrAdd("Working Set" + instance, new PerformanceCounter("Process", "Working Set", instance));
+                var ramCounter = Counters.GetOrAdd("Working Set" + instance, () => new PerformanceCounter("Process", "Working Set", instance));
                 var mb = ramCounter.NextValue() / 1024 / 1024;
                 var mb = ramCounter.NextValue() / 1024 / 1024;
-                return (process, mb);
+                return mb;
             }
             }
-            return (process, 0);
+            return 0;
         }
         }
 
 
         #endregion 内存相关
         #endregion 内存相关

+ 8 - 165
Masuit.Tools.Abstractions/Models/TreeExtensions.cs

@@ -109,32 +109,10 @@ public static class TreeExtensions
     {
     {
         if (p == null)
         if (p == null)
         {
         {
-            yield break;
+            return [];
         }
         }
 
 
-        // 使用一个队列来存储待处理的节点
-        var queue = new Queue<T>();
-        queue.Enqueue(p);
-
-        while (queue.Count > 0)
-        {
-            // 从队列中出队一个节点
-            var currentItem = queue.Dequeue();
-
-            // 将当前节点返回
-            yield return currentItem;
-
-            // 获取当前节点的子节点,如果子节点列表不存在,则初始化为空列表
-            var children = currentItem.Children ?? new List<T>();
-
-            // 将所有子节点入队
-            foreach (var child in children)
-            {
-                // 执行平铺时的操作(如果有的话)
-                optionAction?.Invoke(child, currentItem);
-                queue.Enqueue(child);
-            }
-        }
+        return Flatten([p], t => t.Children, optionAction);
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -193,32 +171,10 @@ public static class TreeExtensions
     {
     {
         if (items == null)
         if (items == null)
         {
         {
-            yield break;
-        }
-
-        // 使用一个栈来存储待处理的节点
-        var stack = new Stack<Tree<T>>();
-        // 首先将所有项压入栈中
-        foreach (var item in items)
-        {
-            stack.Push(item);
+            return [];
         }
         }
 
 
-        // 循环直到栈为空
-        while (stack.Count > 0)
-        {
-            // 弹出栈顶的节点
-            var currentItem = stack.Pop();
-            yield return currentItem;
-
-            // 为当前节点设置子节点,如果optionAction不为空,则对每个子节点执行操作
-            var children = currentItem.Children ?? new List<Tree<T>>();
-            foreach (var child in children)
-            {
-                optionAction?.Invoke(child, currentItem);
-                stack.Push(child); // 将子节点压入栈中
-            }
-        }
+        return Flatten(items, t => t.Children, optionAction);
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -232,33 +188,10 @@ public static class TreeExtensions
     {
     {
         if (p == null)
         if (p == null)
         {
         {
-            yield break;
+            return [];
         }
         }
 
 
-        // 使用一个队列来存储待处理的节点
-        var queue = new Queue<Tree<T>>();
-        queue.Enqueue(p);
-
-        // 遍历队列直到它为空
-        while (queue.Count > 0)
-        {
-            // 从队列中取出当前节点
-            var currentItem = queue.Dequeue();
-
-            // 将当前节点返回
-            yield return currentItem;
-
-            // 获取当前节点的子节点列表,如果为空则初始化为空列表
-            var children = currentItem.Children ?? new List<Tree<T>>();
-
-            // 将所有子节点添加到队列中
-            foreach (var child in children)
-            {
-                // 执行平铺时的操作(如果有的话)
-                optionAction?.Invoke(child, currentItem);
-                queue.Enqueue(child);
-            }
-        }
+        return Flatten([p], t => t.Children, optionAction);
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -499,102 +432,12 @@ public static class TreeExtensions
 
 
     internal static IEnumerable<T> BuildTree<T, TKey>(IEnumerable<T> source, TKey? topValue = default) where T : ITreeEntity<T, TKey> where TKey : struct, IComparable
     internal static IEnumerable<T> BuildTree<T, TKey>(IEnumerable<T> source, TKey? topValue = default) where T : ITreeEntity<T, TKey> where TKey : struct, IComparable
     {
     {
-        // 创建一个字典,用于快速查找节点的子节点
-        var childrenLookup = new NullableDictionary<TKey, List<T>>();
-        var list = source as ICollection<T> ?? source.ToList();
-        foreach (var item in list.Where(item => !childrenLookup.ContainsKey(item.Id)))
-        {
-            childrenLookup[item.Id] = new List<T>();
-        }
-
-        // 构建树结构
-        foreach (var item in list.Where(item => (item.ParentId != null || !Equals(item.ParentId, default(TKey))) && childrenLookup.ContainsKey(item.ParentId ?? default)))
-        {
-            childrenLookup[item.ParentId ?? default].Add(item);
-        }
-
-        // 找到根节点,即没有父节点的节点
-        foreach (var root in list.Where(x => Equals(x.ParentId, topValue)))
-        {
-            // 为根节点和所有子节点设置Children属性
-            // 使用队列来模拟递归过程
-            var queue = new Queue<T>();
-            queue.Enqueue(root);
-            while (queue.Count > 0)
-            {
-                // 出队当前节点
-                var current = queue.Dequeue();
-
-                // 为当前节点设置子节点
-                if (childrenLookup.TryGetValue(current.Id, out var children))
-                {
-                    current.Children = children;
-                    foreach (var child in children)
-                    {
-                        // 如果子节点实现了ITreeParent接口,则设置其Parent属性
-                        if (child is ITreeParent<T> tree)
-                        {
-                            tree.Parent = current;
-                        }
-
-                        // 将子节点入队以继续处理
-                        queue.Enqueue(child);
-                    }
-                }
-            }
-
-            yield return root;
-        }
+        return BuildTree(source, t => t.Id, t => t.ParentId, topValue);
     }
     }
 
 
     internal static IEnumerable<T> BuildTree<T>(IEnumerable<T> source, string topValue = null) where T : ITreeEntity<T>
     internal static IEnumerable<T> BuildTree<T>(IEnumerable<T> source, string topValue = null) where T : ITreeEntity<T>
     {
     {
-        // 创建一个字典,用于快速查找节点的子节点
-        var childrenLookup = new NullableDictionary<string, List<T>>();
-        var list = source as ICollection<T> ?? source.ToList();
-        foreach (var item in list.Where(item => !childrenLookup.ContainsKey(item.Id)))
-        {
-            childrenLookup[item.Id] = new List<T>();
-        }
-
-        // 构建树结构
-        foreach (var item in list.Where(item => !string.IsNullOrEmpty(item.ParentId) && childrenLookup.ContainsKey(item.ParentId)))
-        {
-            childrenLookup[item.ParentId].Add(item);
-        }
-
-        // 找到根节点,即没有父节点的节点
-        foreach (var root in list.Where(x => Equals(x.ParentId, topValue)))
-        {
-            // 为根节点和所有子节点设置Children属性
-            // 使用队列来模拟递归过程
-            var queue = new Queue<T>();
-            queue.Enqueue(root);
-            while (queue.Count > 0)
-            {
-                // 出队当前节点
-                var current = queue.Dequeue();
-
-                // 为当前节点设置子节点
-                if (childrenLookup.TryGetValue(current.Id, out var children))
-                {
-                    current.Children = children;
-                    foreach (var child in children)
-                    {
-                        // 如果子节点实现了ITreeParent接口,则设置其Parent属性
-                        if (child is ITreeParent<T> tree)
-                        {
-                            tree.Parent = current;
-                        }
-
-                        // 将子节点入队以继续处理
-                        queue.Enqueue(child);
-                    }
-                }
-            }
-
-            yield return root;
-        }
+        return BuildTree(source, t => t.Id, t => t.ParentId, topValue);
     }
     }
 
 
     internal static IEnumerable<T> BuildTree<T>(IEnumerable<T> source, T parent) where T : ITreeEntity<T>
     internal static IEnumerable<T> BuildTree<T>(IEnumerable<T> source, T parent) where T : ITreeEntity<T>

+ 1 - 1
Test/Masuit.Tools.Abstractions.Test/Tree/TreeTest.cs

@@ -54,7 +54,7 @@ public class TreeTest
         Assert.Equal(tree[0].AllChildren().Count, 1498);
         Assert.Equal(tree[0].AllChildren().Count, 1498);
         List<MyClass> a = tree.Filter(c => c.Id == 39999).ToList();
         List<MyClass> a = tree.Filter(c => c.Id == 39999).ToList();
         Assert.Equal(a[0].Id, 39999);
         Assert.Equal(a[0].Id, 39999);
-        List<MyClass> raw = tree.Flatten().ToList();
+        List<MyClass> raw = tree.Flatten(c => c.Children).ToList();
         Assert.Equal(raw.Count, list.Count);
         Assert.Equal(raw.Count, list.Count);
         List<MyClass> allParent = a[0].AllParent();
         List<MyClass> allParent = a[0].AllParent();
         Assert.Equal(allParent[0].AllChildren().Count, 19999);
         Assert.Equal(allParent[0].AllChildren().Count, 19999);