diff --git a/DH.Commons/DH.Commons.csproj b/DH.Commons/DH.Commons.csproj
index 62425ed..1cbfe74 100644
--- a/DH.Commons/DH.Commons.csproj
+++ b/DH.Commons/DH.Commons.csproj
@@ -11,14 +11,7 @@
     <Platforms>AnyCPU;x64</Platforms>
   </PropertyGroup>
 
-
-
-
-
-
-
-
-
+ 
  
   <ItemGroup>
     <PackageReference Include="AntdUI" Version="1.8.9" />
diff --git a/DH.Commons/Helper/AttributeHelper.cs b/DH.Commons/Helper/AttributeHelper.cs
new file mode 100644
index 0000000..5236ed2
--- /dev/null
+++ b/DH.Commons/Helper/AttributeHelper.cs
@@ -0,0 +1,162 @@
+using DH.Commons.Enums;
+using System;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using static DH.Commons.Enums.EnumHelper;
+
+
+namespace DH.Commons.Enums
+{
+    /// <summary>
+    /// 设备特性,指示该信息的设备类型,适用于设备信息和配置信息
+    /// </summary>
+    public class DeviceAttribute : Attribute
+    {
+        /// <summary>
+        /// 设备类型
+        /// </summary>
+        public string TypeCode { get; set; }
+
+        public string TypeDescription { get; set; }
+
+        /// <summary>
+        /// 特性修饰类别
+        /// </summary>
+        public DeviceAttributeType AttrType { get; set; }
+
+        public DeviceAttribute(string typeCode, string typeDesc, EnumHelper.DeviceAttributeType attrType)
+        {
+            TypeCode = typeCode;
+            TypeDescription = typeDesc;
+            AttrType = attrType;
+        }
+    }
+
+    /// <summary>
+    /// 预置状态特性  指定该修饰信息的前置状态允许范围
+    /// </summary>
+    public class PreStateAttribute : Attribute
+    {
+        public int PreState { get; set; }
+        public PreStateAttribute(int _preState)
+        {
+            PreState = _preState;
+        }
+
+        /// <summary>
+        /// 检查当前待执行操作的前置状态要求是否合法
+        /// </summary>
+        /// <param name="currentState"></param>
+        /// <returns></returns>
+        public bool CheckPreStateValid(int currentState)
+        {
+            return (currentState & PreState) == currentState;
+        }
+    }
+
+    public class ColorSelectAttribute : Attribute
+    {
+        public string SelectedColor { get; set; }
+        public ColorSelectAttribute(string selectedColor)
+        {
+            SelectedColor = selectedColor;
+        }
+    }
+
+    public class FontColorSelectAttribute : Attribute
+    {
+        public string SelectedColor { get; set; }
+        public FontColorSelectAttribute(string selectedColor)
+        {
+            SelectedColor = selectedColor;
+        }
+    }
+
+    public enum InvokeType
+    {
+        /// <summary>
+        /// 不公开调用
+        /// </summary>
+        [Description("不公开调用")]
+        NoneInvoke = 0,
+        /// <summary>
+        /// 测试调用
+        /// </summary>
+        [Description("测试调用")]
+        TestInvoke = 1,
+        /// <summary>
+        /// 标定调用
+        /// </summary>
+        [Description("标定调用")]
+        CalibInvoke = 2,
+    }
+
+    /// <summary>
+    /// 用来修饰对外开放的调用方法的特性
+    /// 调用方法参数顺序:IOperationConfig,InvokeDevice,SourceDevice
+    /// </summary>
+    public class ProcessMethodAttribute : Attribute
+    {
+        public string MethodCode { get; set; }
+        public string MethodDesc { get; set; }
+
+        /// <summary>
+        /// 是否提供人工调用测试
+        /// </summary>
+        public InvokeType InvokeType { get; set; }
+
+        public string DeviceType { get; set; }
+
+        public ProcessMethodAttribute(string deviceType, string code, string description, InvokeType invokeType)
+        {
+            DeviceType = deviceType;
+            MethodCode = code;
+            MethodDesc = description;
+            InvokeType = invokeType;
+        }
+    }
+
+    public class SwitchDisplayAttribute : Attribute
+    {
+        public string SwitchName { get; set; }
+
+        public bool SwithOnStatus { get; set; } = true;
+
+        public SwitchDisplayAttribute(string name, bool status)
+        {
+            SwitchName = name;
+            SwithOnStatus = status;
+        }
+    }
+
+    public class ElementAttribute : Attribute
+    {
+        public string Name { get; set; }
+
+        public string Desc { get; set; }
+
+        public string IconPath { get; set; }
+
+        public bool IsShowInToolBar { get; set; }
+
+        public ElementAttribute(string desc, string iconPath, bool isShowInToolBar = true, [CallerMemberName] string name = "")
+        {
+            Name = name;
+            Desc = desc;
+            IconPath = iconPath;
+            IsShowInToolBar = isShowInToolBar;
+        }
+    }
+
+    public class ProcessAttribute : Attribute
+    {
+        public string ProcessCode { get; set; }
+        public DeviceAttributeType AttrType { get; set; }
+
+        public ProcessAttribute(string stationCode, DeviceAttributeType attrType)
+        {
+            ProcessCode = stationCode;
+            AttrType = attrType;
+        }
+    }
+}
\ No newline at end of file
diff --git a/DH.Commons/Helper/EnumHelper.cs b/DH.Commons/Helper/EnumHelper.cs
index 019614c..3b0d2a6 100644
--- a/DH.Commons/Helper/EnumHelper.cs
+++ b/DH.Commons/Helper/EnumHelper.cs
@@ -251,7 +251,38 @@ namespace DH.Commons.Enums
             [Description("测量结果")]
             MeasureResult = 31,
         }
-
+       
+        public enum LogLevel
+        {
+            [Description("详细")]
+            [ColorSelect("White")]
+            [FontColorSelect("Green")]
+            Detail = 2,
+            [Description("信息")]
+            [ColorSelect("White")]
+            [FontColorSelect("Dark")]
+            Information = 3,
+            [Description("辅助")]
+            [ColorSelect("White")]
+            [FontColorSelect("Blue")]
+            Assist = 4,
+            [Description("动作")]
+            [ColorSelect("DarkGreen")]
+            [FontColorSelect("Yellow")]
+            Action = 5,
+            [Description("错误")]
+            [ColorSelect("Orange")]
+            [FontColorSelect("White")]
+            Error = 6,
+            [Description("警报")]
+            [ColorSelect("Brown")]
+            [FontColorSelect("White")]
+            Warning = 7,
+            [Description("异常")]
+            [ColorSelect("Red")]
+            [FontColorSelect("White")]
+            Exception = 8,
+        }
         //public enum CameraDriverType
         //{
         //    Halcon,
diff --git a/DH.Commons/Helper/LoggerHelper.cs b/DH.Commons/Helper/LoggerHelper.cs
new file mode 100644
index 0000000..eba4c68
--- /dev/null
+++ b/DH.Commons/Helper/LoggerHelper.cs
@@ -0,0 +1,126 @@
+using DH.Commons.Helper;
+using System;
+using System.Collections.Concurrent;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using static DH.Commons.Enums.EnumHelper;
+
+namespace DH.Commons.Enums
+{
+    public class LoggerHelper
+    {
+        public event Action<DateTime, string> OnLogExceptionRaised;
+
+        public string LogPath { get; set; }
+        public string LogPrefix { get; set; }
+
+        LogLevel LogLevel = LogLevel.Information;
+
+        public LoggerHelper() { }
+        public LoggerHelper(string logPath, string logPrefix, LogLevel logLevel = LogLevel.Information)
+        {
+            LogPath = logPath;
+            LogPrefix = logPrefix;
+
+            LogLevel = logLevel;
+        }
+
+        public void SetLogLevel(LogLevel logLevel)
+        {
+            if (LogLevel != logLevel)
+                LogLevel = logLevel;
+        }
+        ////耗时操作从 _taskFactory分配线程
+        //public TaskFactory _taskFactory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.LongRunning);
+        readonly ConcurrentQueue<LogMsg> _logQueue = new ConcurrentQueue<LogMsg>();
+        Task _logTask = null;
+        readonly object _logLock = new object();
+
+        public async void LogAsync(LogMsg msg)
+        {
+            await Task.Run(() =>
+            {
+                _logQueue.Enqueue(msg);
+
+                lock (_logLock)
+                {
+                    if (_logTask == null)
+                    {
+                        _logTask = Task.Run(async () =>
+                        {
+                            string filePath = Path.Combine(LogPath, $"{(string.IsNullOrWhiteSpace(LogPrefix) ? "Log_" : ("Log_" + LogPrefix + "_"))}{DateTime.Now.ToString("yyyyMMdd")}.txt");
+                            try
+                            {
+                                if (!StaticHelper.CheckFilesCanUse(filePath))
+                                {
+                                    OnLogExceptionRaised?.Invoke(DateTime.Now, $"日志文件{filePath}被占用,无法写入");
+                                    return;
+                                }
+                                using (StreamWriter writer = new StreamWriter(filePath, true, System.Text.Encoding.UTF8))
+                                {
+                                    while (true)
+                                    {
+                                        if (!Directory.Exists(LogPath))
+                                        {
+                                            Directory.CreateDirectory(LogPath);
+                                        }
+
+                                        while (_logQueue.Count > 0)
+                                        {
+                                            if (_logQueue.TryDequeue(out LogMsg log))
+                                            {
+                                                if (log.LogLevel >= LogLevel)
+                                                {
+                                                    writer.WriteLine($"{log.LogTime.ToString("yyyy-MM-dd HH:mm:ss.fff")}[{log.ThreadId}]\t{log.LogLevel.GetEnumDescription()}\t{log.Msg}");
+                                                }
+                                            }
+                                        }
+                                        writer.Flush();
+
+                                        await Task.Delay(2000);
+                                    }
+                                }
+                            }
+                            catch (Exception ex)
+                            {
+                                //OnLogExceptionRaised?.Invoke(DateTime.Now, $"日志文件{filePath}写入异常:/*{ex.GetExceptionMessage()*/}");
+                                OnLogExceptionRaised?.Invoke(DateTime.Now, $"日志文件{filePath}写入异常");
+                            }
+                        });
+                    }
+                }
+            });
+        }
+
+        public void LogAsync(DateTime dt, LogLevel logLevel, string msg)
+        {
+            LogAsync(new LogMsg(dt, logLevel, msg));
+        }
+    }
+
+    public class LogMsg
+    {
+        public DateTime LogTime { get; set; }
+        public LogLevel LogLevel { get; set; }
+        //public string Prefix { get; set; }
+        public string Msg { get; set; }
+
+        public string MsgSource { get; set; }
+
+        public int ThreadId { get; set; }
+
+        public LogMsg() { }
+        public LogMsg(DateTime dt, LogLevel logLevel, string msg)
+        {
+            LogTime = dt;
+            LogLevel = logLevel;
+            Msg = msg;
+        }
+
+        public override string ToString()
+        {
+            return $"{LogTime.ToString("HH:mm:ss.fff")}\t{MsgSource}\t{Msg}";
+        }
+    }
+}
diff --git a/DH.Commons/Helper/StaticHelper.cs b/DH.Commons/Helper/StaticHelper.cs
new file mode 100644
index 0000000..e80421b
--- /dev/null
+++ b/DH.Commons/Helper/StaticHelper.cs
@@ -0,0 +1,677 @@
+using Microsoft.CSharp.RuntimeBinder;
+
+using System.Collections.ObjectModel;
+using System.Drawing.Imaging;
+using System.Dynamic;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.ExceptionServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization.Formatters.Binary;
+
+namespace DH.Commons.Helper
+{
+    public static class StaticHelper
+    {
+        /// <summary>
+        /// 数值转换为byte数组 高位在前,低位在后
+        /// </summary>
+        /// <param name="number"></param>
+        /// <param name="size"></param>
+        /// <returns></returns>
+        public static byte[] IntToBytes(this int number, int size = 2)
+        {
+            byte[] result = new byte[size];
+
+            int temp = size;
+            while (temp > 0)
+            {
+                result[size - temp] = (byte)(number >> ((temp - 1) * 8) & 0xff);
+
+                temp--;
+            }
+
+            return result;
+        }
+
+        /// <summary>
+        /// 字节数组转换为整数
+        /// </summary>
+        /// <param name="data">字节数组</param>
+        /// <param name="HtL">true:数组序号低的在高位 false:数组序号低的在低位</param>
+        /// <returns></returns>
+        public static int BytesToInt(this byte[] data, bool HtL = true)
+        {
+            int res = 0;
+
+            for (int i = 0; i < data.Length; i++)
+            {
+                int index = i;
+
+                if (HtL)
+                {
+                    index = data.Length - 1 - i;
+                }
+
+                res += data[index] << (8 * i);
+            }
+
+            return res;
+        }
+
+        /// <summary>
+        /// 获取一个类指定的属性值
+        /// </summary>
+        /// <param name="info">object对象</param>
+        /// <param name="field">属性名称</param>
+        /// <returns></returns>
+        public static object GetPropertyValue(object info, string field)
+        {
+            if (info == null) return null;
+            Type t = info.GetType();
+            IEnumerable<System.Reflection.PropertyInfo> property = from pi in t.GetProperties() where pi.Name.ToLower() == field.ToLower() select pi;
+            return property.First().GetValue(info, null);
+        }
+
+        /// <summary>
+        /// 将32位整形拆分为无符号16位整形
+        /// </summary>
+        /// <param name="num">需要拆分的32位整形</param>
+        /// <param name="bitNum">拆分为16位整形的位数 1或者2</param>
+        /// <param name="HtL">true:高位在前,低位在后;false:高位在后,低位在前</param>
+        /// <returns></returns>
+        public static List<ushort> ParseIntToUnsignShortList(this int num, int bitNum = 2, bool HtL = false)
+        {
+            if (bitNum == 2)
+            {
+                ushort high = (ushort)(num >> 16);
+                ushort low = (ushort)num;
+
+                if (HtL)
+                {
+                    return new List<ushort>() { high, low };
+                }
+                else
+                {
+                    return new List<ushort>() { low, high };
+                }
+            }
+            else
+            {
+                if (num < 0)
+                {
+                    num = ushort.MaxValue + 1 + num;
+                }
+
+                return new List<ushort>() { (ushort)num };
+            }
+        }
+
+        /// <summary>
+        /// 将32位整形数组拆分为无符号16位整形数组
+        /// </summary>
+        /// <param name="list">需要拆分的32位整形</param>
+        /// <param name="bitNum">拆分为16位整形的位数 1或者2</param>
+        /// <param name="HtL">true:高位在前,低位在后;false:高位在后,低位在前</param>
+        /// <returns></returns>
+        public static List<ushort> ParseIntToUnsignShortList(this List<int> list, int bitNum = 2, bool HtL = false)
+        {
+            return list.SelectMany(u => u.ParseIntToUnsignShortList(bitNum, HtL)).ToList();
+        }
+
+        /// <summary>
+        /// 将ushort的集合转换为16位带符号整形
+        /// </summary>
+        /// <param name="numList"></param>
+        /// <param name="bitNum">合并的位数 1或者2</param>
+        /// <param name="HtL">true:高位在前,低位在后;false:高位在后,低位在前</param>
+        /// <returns></returns>
+        public static List<int> ParseUnsignShortListToInt(this List<int> numList, int bitNum = 2, bool HtL = false)
+        {
+            if (bitNum == 1)
+            {
+                return numList.ConvertAll(n =>
+                {
+                    int num = n;
+                    if (num > short.MaxValue)
+                    {
+                        num = num - ushort.MaxValue - 1;
+                    }
+
+                    return num;
+                });
+            }
+            else
+            {
+                List<int> list = new List<int>();
+                for (int i = 0; i < numList.Count; i += 2)
+                {
+                    int high = HtL ? numList[i] : numList[i + 1];
+                    int low = HtL ? numList[i + 1] : numList[i];
+                    list.Add((high << 16) | low);
+                }
+
+                return list;
+            }
+        }
+
+        //public static T DeepSerializeClone<T>(this T t)
+        //{
+        //    return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(t));
+        //}
+
+        public static void DataFrom<T1, T2>(this T1 destT, T2 sourceT, List<string> exceptionProps = null) where T1 : class where T2 : class
+        {
+            if (sourceT == null)
+            {
+                destT = null;
+                return;
+            }
+
+            PropertyInfo[] propDest = destT.GetType().GetProperties();//.Where(p => !(p.GetMethod.IsVirtual && !p.GetMethod.IsFinal)).ToArray();
+            PropertyInfo[] propSource = sourceT.GetType().GetProperties();
+
+            Array.ForEach(propDest, prop =>
+            {
+                if (exceptionProps == null || !exceptionProps.Contains(prop.Name))
+                {
+                    if (prop.CanWrite)
+                    {
+                        PropertyInfo propS = propSource.FirstOrDefault(p => p.Name == prop.Name);
+                        if (propS != null && propS.CanRead)
+                        {
+                            prop.SetValue(destT, propS.GetValue(sourceT));
+                        }
+                    }
+                }
+            });
+        }
+
+       
+        //RtlMoveMemory
+        [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
+        public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
+        [HandleProcessCorruptedStateExceptions]
+        //public static Bitmap CopyBitmap(this Bitmap source)
+        //{
+        //    Bitmap clone = new Bitmap(source.Width, source.Height, source.PixelFormat);
+        //    try
+        //    {
+        //        int PixelSize = Bitmap.GetPixelFormatSize(source.PixelFormat) / 8;
+        //        if (PixelSize == 1)
+        //        {
+        //            ColorPalette cp = clone.Palette;
+        //            for (int i = 0; i < 256; i++)
+        //            {
+        //                cp.Entries[i] = Color.FromArgb(255, i, i, i);
+        //            }
+        //            clone.Palette = cp;
+        //        }
+
+        //        Rectangle rect = new Rectangle(0, 0, source.Width, source.Height);
+        //        BitmapData sourceData = source.LockBits(rect, ImageLockMode.ReadWrite, source.PixelFormat);
+        //        BitmapData cloneData = clone.LockBits(rect, ImageLockMode.ReadWrite, source.PixelFormat);
+        //        if (source.Width % 4 == 0)
+        //        {
+        //            unsafe
+        //            {
+        //                CopyMemory(cloneData.Scan0, sourceData.Scan0, (uint)(sourceData.Stride * sourceData.Height));
+        //            }
+        //        }
+        //        else
+        //        {
+        //            Parallel.For(0, source.Height, h =>
+        //            {
+        //                unsafe
+        //                {
+        //                    CopyMemory(cloneData.Scan0 + h * sourceData.Stride, sourceData.Scan0 + h * sourceData.Stride, (uint)sourceData.Width);
+        //                }
+        //            });
+        //        }
+
+        //        clone.UnlockBits(cloneData);
+        //        source.UnlockBits(sourceData);
+
+        //    }
+        //    catch (Exception ex)
+        //    {
+        //        return clone;
+        //    }
+
+        //    return clone;
+        //}
+        public static Bitmap CopyBitmap(this Bitmap source)
+        {
+            Bitmap clone = new Bitmap(source.Width, source.Height, source.PixelFormat);
+
+            try
+            {
+                int pixelSize = Bitmap.GetPixelFormatSize(source.PixelFormat) / 8;
+                if (pixelSize == 1)
+                {
+                    ColorPalette cp = clone.Palette;
+                    for (int i = 0; i < 256; i++)
+                    {
+                        cp.Entries[i] = Color.FromArgb(255, i, i, i);
+                    }
+                    clone.Palette = cp;
+                }
+
+                Rectangle rect = new Rectangle(0, 0, source.Width, source.Height);
+                BitmapData sourceData = source.LockBits(rect, ImageLockMode.ReadOnly, source.PixelFormat);
+                BitmapData cloneData = clone.LockBits(rect, ImageLockMode.WriteOnly, source.PixelFormat);
+
+                int stride = sourceData.Stride;
+                int height = sourceData.Height;
+
+                if (stride % 4 == 0)
+                {
+                    unsafe
+                    {
+                        CopyMemory(cloneData.Scan0, sourceData.Scan0, (uint)(stride * height));
+                    }
+                }
+                else
+                {
+                    Parallel.For(0, height, h =>
+                    {
+                    unsafe
+                    {
+                        CopyMemory(cloneData.Scan0 + h * stride, sourceData.Scan0 + h * stride, (uint)stride);
+                        }
+                    });
+                }
+                source.UnlockBits(sourceData); clone.UnlockBits(cloneData);
+            }
+            catch (Exception ex)
+            { // Handle or log exception if needed
+            } return clone; } 
+
+
+                public static Bitmap BitmapDeepClone(Bitmap source)
+        {
+            Bitmap clone = new Bitmap(source.Width, source.Height, source.PixelFormat);
+
+            try
+            {
+                int PixelSize = Bitmap.GetPixelFormatSize(source.PixelFormat) / 8;
+                if (PixelSize == 1)
+                {
+                    ColorPalette cp = clone.Palette;
+                    for (int i = 0; i < 256; i++)
+                    {
+                        cp.Entries[i] = Color.FromArgb(255, i, i, i);
+                    }
+                    clone.Palette = cp;
+                }
+                Rectangle rect = new Rectangle(0, 0, source.Width, source.Height);
+                BitmapData source_bitmap = source.LockBits(rect, ImageLockMode.ReadWrite, source.PixelFormat);
+                BitmapData destination_bitmap = clone.LockBits(rect, ImageLockMode.ReadWrite, clone.PixelFormat);
+
+                int depth_width = source_bitmap.Width * PixelSize;
+
+                unsafe
+                {
+                    byte* source_ptr = (byte*)source_bitmap.Scan0;
+                    byte* destination_ptr = (byte*)destination_bitmap.Scan0;
+
+                    int offset = source_bitmap.Stride - depth_width;
+
+                    for (int i = 0; i < source_bitmap.Height; i++)
+                    {
+                        for (int j = 0; j < depth_width; j++, source_ptr++, destination_ptr++)
+                        {
+                            *destination_ptr = *source_ptr;
+                        }
+
+                        source_ptr += offset;
+                        destination_ptr += offset;
+                    }
+                }
+
+                source.UnlockBits(source_bitmap);
+                clone.UnlockBits(destination_bitmap);
+            }
+            catch (Exception ex)
+            {
+
+            }
+            return clone;
+        }
+
+
+
+        public static Bitmap HConnectBitmap(this Bitmap map1, Bitmap map2)
+        {
+            Bitmap connectImage = null;
+            if (map1 == null || map2 == null)
+                return null;
+            //横向拼接
+            int width = map1.Width + map2.Width;
+            //高度不变
+            int height = Math.Max(map1.Height, map2.Height);
+            connectImage = new Bitmap(width, height);
+            using (Graphics graph = Graphics.FromImage(connectImage))
+            {
+                graph.DrawImage(connectImage, width, height);
+                graph.Clear(System.Drawing.Color.White);
+                graph.DrawImage(map1, 0, 0);
+                graph.DrawImage(map2, map1.Width, 0);
+            }
+            return connectImage;
+        }
+
+        public static IntPtr FloatToIntptr(float[] bytes)
+        {
+            GCHandle hObject = GCHandle.Alloc(bytes, GCHandleType.Pinned);
+            return hObject.AddrOfPinnedObject();
+        }
+
+        // 将Btimap类转换为byte[]类函数
+        public static byte[] GetBGRValues(Bitmap bmp, out int stride)
+        {
+            var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
+            var bmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);
+            stride = bmpData.Stride;
+            var rowBytes = bmpData.Width * Image.GetPixelFormatSize(bmp.PixelFormat) / 8;
+            var imgBytes = bmp.Height * rowBytes;
+            byte[] rgbValues = new byte[imgBytes];
+            IntPtr ptr = bmpData.Scan0;
+            for (var i = 0; i < bmp.Height; i++)
+            {
+                Marshal.Copy(ptr, rgbValues, i * rowBytes, rowBytes);
+                ptr += bmpData.Stride;
+            }
+            bmp.UnlockBits(bmpData);
+            return rgbValues;
+        }
+        /// <summary>
+        /// 缺陷灰度图转彩色图像函数
+        /// </summary>
+        /// <param name="src">灰度图</param>
+        /// <returns>返回构造的伪彩色图像</returns>
+        public static Bitmap GrayMapToColorMap(this Bitmap src, Dictionary<int, Color> indexColorDict = null)
+        {
+            try
+            {
+                //Stopwatch sw = new Stopwatch();
+                //sw.Start();
+
+                Bitmap dest = new Bitmap(src.Width, src.Height, PixelFormat.Format32bppArgb);
+
+                int destHeight = dest.Height;
+                int destWidth = dest.Width;
+
+                Rectangle rect = new Rectangle(0, 0, destWidth, destHeight);
+                BitmapData bmpDataDest = dest.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
+                BitmapData bmpDataSrc = src.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
+                int strideDest = bmpDataDest.Stride;
+
+                int strideSrc = bmpDataSrc.Stride;
+                unsafe
+                {
+                    byte* pDest = (byte*)bmpDataDest.Scan0.ToPointer();
+                    byte* pSrc = (byte*)bmpDataSrc.Scan0.ToPointer();
+
+                    Parallel.For(0, destHeight, y =>
+                    {
+                        Parallel.For(0, destWidth, x =>
+                        {
+                            int pixel = pSrc[y * strideSrc + x];
+                            int startIndex = y * strideDest + x * 4;
+                            if (pixel >= 0 && pixel <= 63)
+                            {
+                                Color color = Color.Red;
+                                if (indexColorDict != null && indexColorDict.ContainsKey(pixel))
+                                {
+                                    color = indexColorDict[pixel];
+                                }
+
+                                byte R = color.R;
+                                byte G = color.G;
+                                byte B = color.B;
+
+                                pDest[startIndex] = B;
+                                pDest[startIndex + 1] = G;
+                                pDest[startIndex + 2] = R;
+                                pDest[startIndex + 3] = 100;
+                            }
+                            else
+                            {
+                                pDest[startIndex] = 255;
+                                pDest[startIndex + 1] = 255;
+                                pDest[startIndex + 2] = 255;
+                                pDest[startIndex + 3] = 0;
+                            }
+                        });
+                    });
+                }
+                dest.UnlockBits(bmpDataDest);
+                src.UnlockBits(bmpDataSrc);
+
+                //sw.Stop();
+                //Console.WriteLine($"转换耗时:{sw.ElapsedMilliseconds}");
+
+                return dest;
+            }
+            catch (Exception ex)
+            {
+                return null;
+            }
+        }
+
+        public static void Sort<T>(this ObservableCollection<T> collection) where T : IComparable<T>
+        {
+            List<T> sortedList = collection.OrderByDescending(x => x).ToList();//这里用降序 
+            for (int i = 0; i < sortedList.Count(); i++)
+            {
+                collection.Move(collection.IndexOf(sortedList[i]), i);
+            }
+        }
+
+        /// <summary>
+        /// 获得字符串中开始和结束字符串中间的值
+        /// </summary>
+        /// <param name="sourse"></param>
+        /// <param name="startstr"></param>
+        /// <param name="endstr"></param>
+        /// <returns></returns>
+        public static string GetMidString(string sourse, string startstr, string endstr)
+        {
+            string result = string.Empty;
+            int startindex, endindex;
+            try
+            {
+                startindex = sourse.IndexOf(startstr);
+                if (startindex == -1)
+                    return result;
+                string tmpstr = sourse.Substring(startindex + startstr.Length);
+                endindex = tmpstr.IndexOf(endstr);
+                if (endindex == -1)
+                    return result;
+                result = tmpstr.Remove(endindex);
+            }
+            catch (Exception ex)
+            {
+                return "";
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// 获得字符串中开始和结束字符串中间的值
+        /// </summary>
+        /// <param name="t">字符串</param>
+        /// <param name="k">开始</param>
+        /// <param name="j">结束</param>
+        /// <returns></returns> 
+        private static string GetMidString2(string sourse, string startstr, string endstr) //截取指定文本,和易语言的取文本中间差不多
+        {
+            try //异常捕捉
+            {
+                var kn = sourse.IndexOf(startstr, StringComparison.Ordinal) + startstr.Length;
+                var jn = sourse.IndexOf(endstr, kn, StringComparison.Ordinal);
+                return sourse.Substring(kn, jn - kn);
+            }
+            catch //如果发现未知的错误,比如上面的代码出错了,就执行下面这句代码
+            {
+                return ""; //返回空
+            }
+
+        }
+
+        // 布尔类型转换为整型
+        public static int ToInt(this object obj)
+        {
+            if (Convert.ToBoolean(obj) == true)
+                return 1;
+            else
+                return 0;
+        }
+
+        // 整型转换为布尔类型
+        public static bool ToBool(this object obj)
+        {
+            if (Convert.ToInt32(obj) == 1)
+                return true;
+            else
+                return false;
+        }
+
+        public static object GetProperty(this object o, string member)
+        {
+            if (o == null) throw new ArgumentNullException("o");
+            if (member == null) throw new ArgumentNullException("member");
+            Type scope = o.GetType();
+            IDynamicMetaObjectProvider provider = o as IDynamicMetaObjectProvider;
+            if (provider != null)
+            {
+                ParameterExpression param = Expression.Parameter(typeof(object));
+                DynamicMetaObject mobj = provider.GetMetaObject(param);
+                GetMemberBinder binder = (GetMemberBinder)Microsoft.CSharp.RuntimeBinder.Binder.GetMember(0, member, scope, new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(0, null) });
+                DynamicMetaObject ret = mobj.BindGetMember(binder);
+                BlockExpression final = Expression.Block(
+                    Expression.Label(CallSiteBinder.UpdateLabel),
+                    ret.Expression
+                );
+                LambdaExpression lambda = Expression.Lambda(final, param);
+                Delegate del = lambda.Compile();
+                return del.DynamicInvoke(o);
+            }
+            else
+            {
+                return o.GetType().GetProperty(member, BindingFlags.Public | BindingFlags.Instance).GetValue(o, null);
+            }
+        }
+
+        #region 检测文件状态及操作方式选择
+        [DllImport("kernel32.dll")]
+        private static extern IntPtr _lopen(string lpPathName, int iReadWrite);
+        [DllImport("kernel32.dll")]
+        private static extern bool CloseHandle(IntPtr hObject);
+        private const int OF_READWRITE = 2;
+        private const int OF_SHARE_DENY_NONE = 0x40;
+        private static readonly IntPtr HFILE_ERROR = new IntPtr(-1);
+        /// <summary>
+        /// 检测文件是否只读或被使用
+        /// </summary>
+        /// <param name="FileNames">要检测的文件</param>
+        /// <returns>true可用,false在用或只读</returns>
+        public static bool CheckFilesCanUse(string fileName)
+        {
+            if (!File.Exists(fileName))
+                return true;//文件不存在
+            if ((File.GetAttributes(fileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
+                return false;       //文件只读
+            IntPtr vHandle = _lopen(fileName, OF_READWRITE | OF_SHARE_DENY_NONE);
+            if (vHandle == HFILE_ERROR)
+            {
+                CloseHandle(vHandle);
+                return false;       //文件被占用
+            }
+
+            CloseHandle(vHandle);   //文件没被占用
+            return true;
+        }
+        #endregion
+
+        /// <summary>
+        /// 获取指定文件夹下所有的文件名称
+        /// </summary>
+        /// <param name="folderName">指定文件夹名称,绝对路径</param>
+        /// <param name="fileFilter">文件类型过滤,根据文件后缀名,如:*,*.txt,*.xls</param>
+        /// <param name="isContainSubFolder">是否包含子文件夹</param>
+        /// <returns>ArrayList数组,为所有需要的文件路径名称</returns>
+        public static List<FileInfo> GetAllFilesByFolder(string folderName, string fileFilter, bool isContainSubFolder = false)
+        {
+            List<FileInfo> resList = new List<FileInfo>();
+            try
+            {
+                DirectoryInfo currDir = new DirectoryInfo(folderName);//当前目录
+                FileInfo[] currFiles = currDir.GetFiles(fileFilter);//当前目录文件
+                foreach (FileInfo file in currFiles)
+                {
+                    if (fileFilter.ToLower().IndexOf(file.Extension.ToLower()) >= 0)
+                    {
+                        resList.Add(file);
+                    }
+                }
+                if (isContainSubFolder)
+                {
+                    string[] subFolders = Directory.GetDirectories(folderName);
+                    foreach (string subFolder in subFolders)
+                    {
+                        resList.AddRange(GetAllFilesByFolder(subFolder, fileFilter));//递归   
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                throw ex;
+            }
+            return resList;
+        }
+
+        /// <summary>
+        /// 获取指定文件夹下所有的文件名称,不过滤文件类型
+        /// </summary>
+        /// <param name="folderName">指定文件夹名称,绝对路径</param>
+        /// <param name="isContainSubFolder">是否包含子文件夹</param>
+        /// <returns>ArrayList数组,为所有需要的文件路径名称</returns>
+        public static List<FileInfo> GetAllFilesByFolder(string folderName, bool isContainSubFolder)
+        {
+            return GetAllFilesByFolder(folderName, "*", isContainSubFolder);
+        }
+    }
+
+    public class Compare<T, C> : IEqualityComparer<T>
+    {
+        private Func<T, C> _getField;
+        public Compare(Func<T, C> getfield)
+        {
+            _getField = getfield;
+        }
+        public bool Equals(T x, T y)
+        {
+            return EqualityComparer<C>.Default.Equals(_getField(x), _getField(y));
+        }
+        public int GetHashCode(T obj)
+        {
+            return EqualityComparer<C>.Default.GetHashCode(_getField(obj));
+        }
+    }
+
+    public static class ObjectExtensions
+    {
+        public static IEnumerable<T> DistinctBy<T, C>(this IEnumerable<T> source, Func<T, C> getfield)
+        {
+            return source.Distinct(new Compare<T, C>(getfield));
+        }
+
+        public static IQueryable<T> DistinctBy<T, C>(this IQueryable<T> source, Func<T, C> getfield)
+        {
+            return source.Distinct(new Compare<T, C>(getfield));
+        }
+    }
+}