ソースを参照

20250828001 识别区域判断异步处理优化

向羽 孟 8 ヶ月 前
コミット
1a32c779ee

+ 6 - 4
CCDCountWpf/WpfPage/HistoryDataPage.xaml.cs

@@ -30,12 +30,13 @@ namespace CCDCountWpf.WpfPage
     {
         private static ActionMesSqliteDataClass actionMesSqliteDataClass = null;
         int DataStartLine = 0;
-        private int PageHeight = 2000;
+        private int PageHeight = 1000;
         public HistoryDataPage()
         {
             InitializeComponent();
             DataContext = ShowMessageBus.ShowBinding;
             actionMesSqliteDataClass = new ActionMesSqliteDataClass($"{AppDomain.CurrentDomain.BaseDirectory}DATA\\ActiveObjectData\\Cam{MessageBus.MainThreadS[0].cameraConfig.CamerNo}\\ActiveObjectData{DateTime.Now:yyyyMMdd}.db");
+            //actionMesSqliteDataClass = new ActionMesSqliteDataClass($"{AppDomain.CurrentDomain.BaseDirectory}DATA\\ActiveObjectData\\Cam{MessageBus.MainThreadS[0].cameraConfig.CamerNo}\\ActiveObjectData20250827.db");
             actionMesSqliteDataClass.GetAllActionMinStartMaxEndLine(out int num, out int StartLine, out int EndLine);
             ShowMessageBus.ShowBinding.HistoryImageCount = (EndLine - StartLine)/PageHeight;
             DataStartLine = StartLine;
@@ -74,7 +75,8 @@ namespace CCDCountWpf.WpfPage
             {
                 int ThisImageStartLine = (int)ShowResult.Min(o => o.StartLine);
                 int ImageHeight = (int)(ShowResult.Max(o => o.LastSeenLine) - ShowResult.Min(o => o.StartLine));
-                BitmapImage = new Bitmap(4096, ImageHeight <= PageHeight ? PageHeight : ImageHeight);
+                int ImageWidth = ShowResult.Max(o => o.ImageWidth);
+                BitmapImage = new Bitmap(ImageWidth, ImageHeight <= PageHeight ? PageHeight : ImageHeight);
 
                 using (Graphics g = Graphics.FromImage(BitmapImage))
                 {
@@ -92,8 +94,8 @@ namespace CCDCountWpf.WpfPage
                         int roiwidth = item.MaxEndCol - item.MinStartCol + 10;
                         g.DrawRectangle(GreenPen, new System.Drawing.Rectangle(roix, roiy, roiwidth, roiheight));
 
-                        Font font = new Font("Arial", 40);
-                        g.DrawString(item.Num.ToString(), font, System.Drawing.Brushes.Black, new System.Drawing.Point(roix - 50 * item.Num.ToString().Length, roiy - 20));
+                        Font font = new Font("Arial", 20);
+                        g.DrawString(item.Num.ToString(), font, System.Drawing.Brushes.Black, new System.Drawing.Point(roix - 20 * item.Num.ToString().Length, roiy - 20));
 
                         foreach (var item1 in item.RowsData)
                         {

+ 3 - 3
TestWork.DLL/CameraClass.cs

@@ -305,9 +305,9 @@ namespace CCDCount.DLL
             {
                 //丢帧记录
                 LOG.log(string.Format("lost frame: Width[{0}] , Height[{1}] , FrameNum[{2}] ,Frevous[{3}]",
-                    IFrameData.Image.Width, IFrameData.Image.Height, IFrameData.FrameNum - 1, lastframeNum), 6);
+                    IFrameData.Image.Width, IFrameData.Image.Height, IFrameData.FrameNum , lastframeNum), 6);
                 Console.WriteLine("lost frame: Width[{0}] , Height[{1}] , FrameNum[{2}] ,Frevous[{3}]",
-                    IFrameData.Image.Width, IFrameData.Image.Height, IFrameData.FrameNum - 1, lastframeNum);
+                    IFrameData.Image.Width, IFrameData.Image.Height, IFrameData.FrameNum , lastframeNum);
                 lastframeNum = IFrameData.FrameNum;
             }
             return result;
@@ -394,7 +394,7 @@ namespace CCDCount.DLL
             try
             {
                 if(device == null) return result;
-                device.StreamGrabber.SetImageNodeNum(10);
+                device.StreamGrabber.SetImageNodeNum(30);
                 device.StreamGrabber.StartGrabbing();
                 result = true;
             }

+ 15 - 10
TestWork.DLL/MainThreadClass.cs

@@ -11,11 +11,8 @@ using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Drawing;
-using System.IO;
 using System.Linq;
 using System.Runtime.InteropServices;
-using System.Runtime.Remoting.Messaging;
-using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 
@@ -118,6 +115,7 @@ namespace CCDCount.DLL
             _IsOpenLoadThread = cameraConfig.IsOpenLoad;
             ThisCamerNo = cameraConfig.CamerNo;
             actionMesSqliteDataClass = new ActionMesSqliteDataClass($"{AppDomain.CurrentDomain.BaseDirectory}DATA\\ActiveObjectData\\Cam{cameraConfig.CamerNo}\\ActiveObjectData{DateTime.Now:yyyyMMdd}.db");
+            //actionMesSqliteDataClass = new ActionMesSqliteDataClass($"{AppDomain.CurrentDomain.BaseDirectory}DATA\\ActiveObjectData\\Cam{cameraConfig.CamerNo}\\ActiveObjectData20250827.db");
             actionMesSqliteDataClass.GetAllActionMinStartMaxEndLine(out int num, out int StartLine, out int EndLine);
             shuLiClass.InitCurrentLine(EndLine);
             //shuLiClass.InitNum(num);
@@ -580,13 +578,20 @@ namespace CCDCount.DLL
             {
                 LOG.log(string.Format("输出当前颗粒信息,颗粒编号:{0},开始时间:{1}结束时间:{2},颗粒状态:{3},通道数:{4}",
                     oneActive.Num, oneActive.StartCheckTime.ToString("O"), oneActive.EndCheckTime.ToString("O"), oneActive.StateCode, oneActive.ChannelNO), 6);
-                //Task.Run(() =>
-                //{
-                //    if (actionMesSqliteDataClass != null)
-                //    {
-                //        actionMesSqliteDataClass.InsertActiveObject(oneActive);
-                //    }
-                //});
+                Task.Run(() =>
+                {
+                    if (actionMesSqliteDataClass != null)
+                    {
+                        try
+                        {
+                            actionMesSqliteDataClass.InsertActiveObject(oneActive);
+                        }
+                        catch (Exception ex)
+                        {
+                            LOG.error ("MianThread-Worker_OneGrainCompleted-Task:" + ex.Message);
+                        }
+                    }
+                });
 
                 if (oneActive.StateCode != 7 && oneActive.ChannelNO != -1)
                 {

+ 239 - 186
TestWork.DLL/ShuLiClass.cs

@@ -9,6 +9,7 @@ using System.Diagnostics;
 using System.Drawing;
 using System.IO;
 using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
 using System.Threading;
 using System.Threading.Tasks;
 
@@ -33,6 +34,7 @@ namespace CCDCount.DLL
         private int ChannelWidth = 0;//每个区域的宽度
         private int IdentifyImageWidth = -1;
         private static readonly object _lockObj = new object(); // 专用锁对象\
+        private static readonly object taskLock = new object(); // 异步专用锁
         private int ObjectNum = 0;
         public int ImageNum { get { return IFrameDatas.Count; } }
         #endregion
@@ -96,6 +98,108 @@ namespace CCDCount.DLL
                 result = ProcessLine(image, i);
                 currentLine += 1;
             }
+
+            //识别到结果并输出
+            lock (_lockObj)
+            {
+                // 清理超时未更新的物体
+                var lostObjects = activeObjects
+                .Where(o => (currentLine - o.LastSeenLine) > shuLiConfig.MAX_GAP || (o.LastSeenLine - o.StartLine) > shuLiConfig.MAX_Idetify_Height)
+                .ToList();
+
+                List<ActiveObjectClass> OneActive = new List<ActiveObjectClass>();
+
+                // 有物体转变为活跃物体,返回值转为true
+                if (lostObjects.Count() > 0)
+                {
+                    result = true;
+                    foreach (var item in lostObjects)
+                    {
+                        //噪点判定
+                        if (item.Area < shuLiConfig.NoiseFilter_Threshold)
+                        {
+                            item.StateCode = 9;
+                            //LOG.log(string.Format("噪点过滤,噪点面积:{0}", item.Area), 6);
+                            continue;
+                        }
+                        //转为历史物体,添加缺少的参数
+                        item.Num = ObjectNum += 1;
+                        item.ChannelNO = ActiveChannel(item);
+                        item.EndCheckTime = DateTime.Now;
+                        OneActive.Add(item);
+                        item.MaxLength = GetActionMaxLength(item.RowsData);
+                        if ((item.LastSeenLine - item.StartLine) > shuLiConfig.MAX_Idetify_Height)
+                        {
+                            item.StateCode = 7;
+                            FaultLog.RecordLogMessage("ShuLiClass-ProcessLine:非颗粒,视野异常", 3);
+                            LOG.log(string.Format("ShuLiClass-ProcessLine:非颗粒,视野异常"), 6);
+                            Console.WriteLine("ShuLiClass-ProcessLine:非颗粒,视野异常");
+                        }
+                        else if (shuLiConfig.PandingCode != -1)
+                        {
+                            if (item.StateCode != -1)
+                            {
+                                if (item.StateCode == 8)
+                                {
+                                    LOG.log(string.Format("颗粒编号{0}:疑似叠片或缺损", item.Num));
+                                }
+                            }
+                            else if (item.Area < shuLiConfig.MinArea
+                                && (shuLiConfig.PandingCode == 2 || shuLiConfig.PandingCode == 1))
+                            {
+                                item.StateCode = 5;
+                                LOG.log(string.Format("颗粒编号{0}:面积过小", item.Num));
+                                Console.WriteLine("颗粒编号{0}:面积过小", item.Num);
+                            }
+                            else if (item.Area > shuLiConfig.MaxArea
+                                && (shuLiConfig.PandingCode == 2 || shuLiConfig.PandingCode == 1))
+                            {
+                                item.StateCode = 6;
+                                LOG.log(string.Format("颗粒编号{0}:面积过大", item.Num));
+                                Console.WriteLine("颗粒编号{0}:面积过大", item.Num);
+                            }
+                            else if (item.MaxLength < shuLiConfig.MIN_Object_LENGTH
+                                && (shuLiConfig.PandingCode == 2 || shuLiConfig.PandingCode == 0))
+                            {
+                                item.StateCode = 2;
+                                LOG.log(string.Format("颗粒编号{0}:超短粒", item.Num));
+                                Console.WriteLine("颗粒编号{0}:超短粒", item.Num);
+                            }
+                            else if (item.MaxLength > shuLiConfig.MAX_Object_LENGTH
+                                && (shuLiConfig.PandingCode == 2 || shuLiConfig.PandingCode == 0))
+                            {
+                                item.StateCode = 1;
+                                LOG.log(string.Format("颗粒编号{0}:超长粒", item.Num));
+                                Console.WriteLine("颗粒编号{0}:超长粒", item.Num);
+                            }
+                            else
+                            {
+                                item.StateCode = 0;
+                                LOG.log(string.Format("颗粒编号{0}:正常粒", item.Num));
+                                Console.WriteLine("颗粒编号{0}:正常粒", item.Num);
+                            }
+                        }
+                    }
+
+                    if (OneActive.Count > 0)
+                    {
+                        LOG.log(string.Format("识别完成,首个颗粒编号:{0},颗粒数量:{1}", OneActive[0].Num, OneActive.Count), 6);
+                        //触发回调事件
+                        Task.Run(() =>
+                        {
+                            OnWorkCompleted(OneActive);
+                        });
+                    }
+                }
+                else
+                {
+                    OneActive = null;
+                }
+
+                // 累加到总数并从活跃物体转移到历史物体
+                lostObjects.Where(o => o.Area >= shuLiConfig.NoiseFilter_Threshold && o.StateCode != 7 && o.StateCode != 9).ToList().ForEach(o => TryAdd(historyActiveObjects, o, 2500));
+                lostObjects.ForEach(o => activeObjects.Remove(o));
+            }
             return result;
         }
 
@@ -320,189 +424,14 @@ namespace CCDCount.DLL
                 }
                 IsPrintLightOnError = false;
             }
-            lock (_lockObj)
-            {
-                // 步骤2:处理当前行每个区域
-                for (int i = 0; i < currentRegions.Count; i++)
-                {
-                    var region = currentRegions[i];
-                    // 查找全部可合并的活跃物体(有重叠+在允许间隔内)
-                    var matcheds = activeObjects.Where(o =>
-                        IsOverlapping(o, region) &&
-                        (currentLine - o.LastSeenLine - 1) <= shuLiConfig.MAX_GAP).ToList();
-                    //当有多个可合并的活跃物体时,将多个物体合并
-                    if (matcheds.Count >= 2)
-                    {
-                        // 合并有效区域队列
-                        var CopeRowsData = new List<RowStartEndCol>();
-                        matcheds.ForEach(o => CopeRowsData = CopeRowsData.Concat(o.RowsData).ToList());
-                        // 合并有效区域并保存在新的区域中
-                        var MergeMatched = new ActiveObjectClass
-                        {
-                            MinStartCol = matcheds.Min(o => o.MinStartCol),
-                            MaxEndCol = matcheds.Max(o => o.MaxEndCol),
-                            StartLine = matcheds.Min(o => o.StartLine),
-                            LastSeenLine = matcheds.Max(o => o.LastSeenLine),
-                            LastSeenLineStartCol = matcheds.Min(o => o.LastSeenLineStartCol),
-                            LastSeenLineEndCol = matcheds.Max(o => o.LastSeenLineEndCol),
-                            StartCheckTime = matcheds.Min(o => o.StartCheckTime),
-                            EndCheckTime = matcheds.Max(o => o.EndCheckTime),
-                            Area = matcheds.Sum(o => o.Area),
-                            RowsData = CopeRowsData,
-                            ImageWidth = matcheds.FirstOrDefault().ImageWidth,
-                            //StateCode = 8
-                        };
-                        // 从活跃区域中删除被合并的区域
-                        matcheds.ForEach(o => activeObjects.Remove(o));
-                        // 保存新的区域到活跃区域中
-                        activeObjects.Add(MergeMatched);
-                    }
 
-                    // 搜获可用且可合并的活跃区域
-                    var matched = activeObjects.FirstOrDefault(o =>
-                        IsOverlapping(o, region) &&
-                        (currentLine - o.LastSeenLine - 1) <= shuLiConfig.MAX_GAP);
-                    if (matched != null)
-                    {
-                        // 合并区域:扩展物体边界并更新状态
-                        matched.MinStartCol = Math.Min(matched.MinStartCol, region.Start);
-                        matched.MaxEndCol = Math.Max(matched.MaxEndCol, region.End);
-                        matched.Area += region.End - region.Start + 1;
-                        matched.LastSeenLine = currentLine;
-                        matched.RowsData.Add(new RowStartEndCol
-                        {
-                            StartCol = region.Start,
-                            EndCol = region.End,
-                            RowsCol = currentLine,
-                        });
-                    }
-                    else
-                    {
-                        // 创建新物体(首次出现的区域)
-                        activeObjects.Add(new ActiveObjectClass
-                        {
-                            MinStartCol = region.Start,
-                            MaxEndCol = region.End,
-                            StartLine = currentLine,
-                            LastSeenLine = currentLine,
-                            LastSeenLineStartCol = region.Start,
-                            LastSeenLineEndCol = region.End,
-                            StartCheckTime = DateTime.Now,
-                            Area = region.End - region.Start + 1,
-                            ImageWidth = IdentifyImageWidth,
-                            RowsData = new List<RowStartEndCol> {
-                                new RowStartEndCol {
-                                    StartCol = region.Start,
-                                    EndCol = region.End,
-                                    RowsCol = currentLine,
-                                }
-                            }
-                        });
-                    }
-                }
-                currentRegions.Clear();
-                // 更新有效物体的最后一行的起始点
-                activeObjects.Where(o => o.LastSeenLine == currentLine).ToList().ForEach(o => o.LastSeenLineStartCol = o.RowsData.Where(p => p.RowsCol == currentLine).Min(p => p.StartCol));
-                activeObjects.Where(o => o.LastSeenLine == currentLine).ToList().ForEach(o => o.LastSeenLineEndCol = o.RowsData.Where(p => p.RowsCol == currentLine).Max(p => p.EndCol));
+            MergeCurrentRegions(currentRegions);
 
-                // 步骤3:清理超时未更新的物体
-                var lostObjects = activeObjects
-                    .Where(o => (currentLine - o.LastSeenLine) > shuLiConfig.MAX_GAP || (o.LastSeenLine - o.StartLine) > shuLiConfig.MAX_Idetify_Height)
-                    .ToList();
-
-                List<ActiveObjectClass> OneActive = new List<ActiveObjectClass>();
+            currentRegions.Clear();
+            // 更新有效物体的最后一行的起始点
+            activeObjects.Where(o => o.LastSeenLine == currentLine).ToList().ForEach(o => o.LastSeenLineStartCol = o.RowsData.Where(p => p.RowsCol == currentLine).Min(p => p.StartCol));
+            activeObjects.Where(o => o.LastSeenLine == currentLine).ToList().ForEach(o => o.LastSeenLineEndCol = o.RowsData.Where(p => p.RowsCol == currentLine).Max(p => p.EndCol));
 
-                // 有物体转变为活跃物体,返回值转为true
-                if (lostObjects.Count() > 0)
-                {
-                    result = true;
-                    foreach (var item in lostObjects)
-                    {
-                        //噪点判定
-                        if (item.Area < shuLiConfig.NoiseFilter_Threshold)
-                        {
-                            item.StateCode = 9;
-                            //LOG.log(string.Format("噪点过滤,噪点面积:{0}", item.Area), 6);
-                            continue;
-                        }
-                        //转为历史物体,添加缺少的参数
-                        item.Num = ObjectNum += 1;
-                        item.ChannelNO = ActiveChannel(item);
-                        item.EndCheckTime = DateTime.Now;
-                        OneActive.Add(item);
-                        item.MaxLength = GetActionMaxLength(item.RowsData);
-                        if ((item.LastSeenLine - item.StartLine) > shuLiConfig.MAX_Idetify_Height)
-                        {
-                            item.StateCode = 7;
-                            FaultLog.RecordLogMessage("ShuLiClass-ProcessLine:非颗粒,视野异常", 3);
-                            LOG.log(string.Format("ShuLiClass-ProcessLine:非颗粒,视野异常"), 6);
-                            Console.WriteLine("ShuLiClass-ProcessLine:非颗粒,视野异常");
-                        }
-                        else if (shuLiConfig.PandingCode != -1)
-                        {
-                            if (item.StateCode != -1)
-                            {
-                                if (item.StateCode == 8)
-                                {
-                                    LOG.log(string.Format("颗粒编号{0}:疑似叠片或缺损", item.Num));
-                                }
-                            }
-                            else if (item.Area < shuLiConfig.MinArea
-                                && (shuLiConfig.PandingCode == 2 || shuLiConfig.PandingCode == 1))
-                            {
-                                item.StateCode = 5;
-                                LOG.log(string.Format("颗粒编号{0}:面积过小", item.Num));
-                                Console.WriteLine("颗粒编号{0}:面积过小", item.Num);
-                            }
-                            else if (item.Area > shuLiConfig.MaxArea
-                                && (shuLiConfig.PandingCode == 2 || shuLiConfig.PandingCode == 1))
-                            {
-                                item.StateCode = 6;
-                                LOG.log(string.Format("颗粒编号{0}:面积过大", item.Num));
-                                Console.WriteLine("颗粒编号{0}:面积过大", item.Num);
-                            }
-                            else if (item.MaxLength < shuLiConfig.MIN_Object_LENGTH
-                                && (shuLiConfig.PandingCode == 2 || shuLiConfig.PandingCode == 0))
-                            {
-                                item.StateCode = 2;
-                                LOG.log(string.Format("颗粒编号{0}:超短粒", item.Num));
-                                Console.WriteLine("颗粒编号{0}:超短粒", item.Num);
-                            }
-                            else if (item.MaxLength > shuLiConfig.MAX_Object_LENGTH
-                                && (shuLiConfig.PandingCode == 2 || shuLiConfig.PandingCode == 0))
-                            {
-                                item.StateCode = 1;
-                                LOG.log(string.Format("颗粒编号{0}:超长粒", item.Num));
-                                Console.WriteLine("颗粒编号{0}:超长粒", item.Num);
-                            }
-                            else
-                            {
-                                item.StateCode = 0;
-                                LOG.log(string.Format("颗粒编号{0}:正常粒", item.Num));
-                                Console.WriteLine("颗粒编号{0}:正常粒", item.Num);
-                            }
-                        }
-                    }
-
-                    if (OneActive.Count > 0)
-                    {
-                        LOG.log(string.Format("识别完成,首个颗粒编号:{0},颗粒数量:{1}", OneActive[0].Num, OneActive.Count), 6);
-                        //触发回调事件
-                        Task.Run(() =>
-                        {
-                            OnWorkCompleted(OneActive);
-                        });
-                    }
-                }
-                else
-                {
-                    OneActive = null;
-                }
-
-                // 累加到总数并从活跃物体转移到历史物体
-                lostObjects.Where(o => o.Area >= shuLiConfig.NoiseFilter_Threshold && o.StateCode != 7 && o.StateCode != 9).ToList().ForEach(o => TryAdd(historyActiveObjects, o, 2500));
-                lostObjects.ForEach(o => activeObjects.Remove(o));
-            }
             return result;
         }
 
@@ -511,9 +440,9 @@ namespace CCDCount.DLL
         /// </summary>
         /// <param name="line">当前行像素数组</param>
         /// <returns>有效区域列表(起始/结束位置)</returns>
-        private List<(int Start, int End)> FindValidRegions(IImage image, int RowNo)
+        private List<ValidRegionModelClass> FindValidRegions(IImage image, int RowNo)
         {
-            List<(int Start, int End)> regions = new List<(int Start, int End)>();
+            List<ValidRegionModelClass> regions = new List<ValidRegionModelClass>();
             int start = -1; // 当前区域起始标记
             // 遍历所有像素列
             if (shuLiConfig.IsIdentifyRoiOpen)
@@ -529,7 +458,11 @@ namespace CCDCount.DLL
                         // 检查区域宽度是否达标
                         if (i - start >= shuLiConfig.MIN_OBJECT_WIDTH)
                         {
-                            regions.Add((start, (i - 1) % (int)image.Width)); // 记录有效区域
+                            regions.Add(new ValidRegionModelClass()
+                            {
+                                Start = start, 
+                                End = (i - 1) % (int)image.Width
+                            }); // 记录有效区域
                         }
                         start = -1; // 重置区域标记
                     }
@@ -548,7 +481,11 @@ namespace CCDCount.DLL
                         // 检查区域宽度是否达标
                         if (i - start >= shuLiConfig.MIN_OBJECT_WIDTH)
                         {
-                            regions.Add((start, (i - 1) % (int)image.Width)); // 记录有效区域
+                            regions.Add(new ValidRegionModelClass() 
+                            {
+                                Start = start, 
+                                End = (i - 1) % (int)image.Width
+                            }); // 记录有效区域
                         }
                         start = -1; // 重置区域标记
                     }
@@ -559,7 +496,10 @@ namespace CCDCount.DLL
             // 处理行尾未闭合的区域
             if (start != -1 && image.Width - start >= shuLiConfig.MIN_OBJECT_WIDTH)
             {
-                regions.Add((start, (int)image.Width - 1));
+                regions.Add(new ValidRegionModelClass() {
+                    Start = start,
+                    End = (int)image.Width - 1
+                });
             }
             return regions;
         }
@@ -570,7 +510,7 @@ namespace CCDCount.DLL
         /// <param name="obj">活跃物体</param>
         /// <param name="region">当前区域</param>
         /// <returns>是否发生重叠</returns>
-        private bool IsOverlapping(ActiveObjectClass obj, (int Start, int End) region)
+        private bool IsOverlapping(ActiveObjectClass obj,ValidRegionModelClass region)
         {
             // 判断区域是否不相交的逆条件
             return !(region.End < obj.LastSeenLineStartCol || region.Start > obj.LastSeenLineEndCol);
@@ -708,6 +648,119 @@ namespace CCDCount.DLL
             }
             return true;
         }
+
+        private bool MergeCurrentRegions(List<ValidRegionModelClass> validRegions)
+        {
+            bool Result = false;
+            ExecuteAsyncOperations(validRegions).GetAwaiter().GetResult();
+            return Result;
+        }
+
+        private async Task ExecuteAsyncOperations(List<ValidRegionModelClass> validRegions)
+        {
+            // 创建异步操作任务列表
+            var tasks = new List<Task<string>>();
+            for (int i = 0; i < validRegions.Count; i++)
+            {
+                tasks.Add(AsyncOperation(validRegions[i],i));
+            }
+
+            try
+            {
+                // 等待所有异步操作完成
+                var results = await Task.WhenAll(tasks);
+                Console.WriteLine($"All operations completed: [{string.Join(", ", results)}]");
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"One or more operations failed: {ex.Message}");
+            }
+        }
+
+        private async Task<string> AsyncOperation(ValidRegionModelClass region,int i)
+        {
+            // 模拟异步操作,比如网络请求或I/O操作
+            await Task.Run(() => {
+                lock(taskLock)
+                {
+                    // 查找全部可合并的活跃物体(有重叠+在允许间隔内)
+                    var matcheds = activeObjects.Where(o =>
+                        IsOverlapping(o, region) &&
+                        (currentLine - o.LastSeenLine - 1) <= shuLiConfig.MAX_GAP).ToList();
+                    //当有多个可合并的活跃物体时,将多个物体合并
+                    if (matcheds.Count >= 2)
+                    {
+                        // 合并有效区域队列
+                        var CopeRowsData = new List<RowStartEndCol>();
+                        matcheds.ForEach(o => CopeRowsData = CopeRowsData.Concat(o.RowsData).ToList());
+                        // 合并有效区域并保存在新的区域中
+                        var MergeMatched = new ActiveObjectClass
+                        {
+                            MinStartCol = matcheds.Min(o => o.MinStartCol),
+                            MaxEndCol = matcheds.Max(o => o.MaxEndCol),
+                            StartLine = matcheds.Min(o => o.StartLine),
+                            LastSeenLine = matcheds.Max(o => o.LastSeenLine),
+                            LastSeenLineStartCol = matcheds.Min(o => o.LastSeenLineStartCol),
+                            LastSeenLineEndCol = matcheds.Max(o => o.LastSeenLineEndCol),
+                            StartCheckTime = matcheds.Min(o => o.StartCheckTime),
+                            EndCheckTime = matcheds.Max(o => o.EndCheckTime),
+                            Area = matcheds.Sum(o => o.Area),
+                            RowsData = CopeRowsData,
+                            ImageWidth = matcheds.FirstOrDefault().ImageWidth,
+                            //StateCode = 8
+                        };
+                        // 从活跃区域中删除被合并的区域
+                        matcheds.ForEach(o => activeObjects.Remove(o));
+                        // 保存新的区域到活跃区域中
+                        activeObjects.Add(MergeMatched);
+                    }
+
+                    // 搜获可用且可合并的活跃区域
+                    var matched = activeObjects.FirstOrDefault(o =>
+                        IsOverlapping(o, region) &&
+                        (currentLine - o.LastSeenLine - 1) <= shuLiConfig.MAX_GAP);
+                    if (matched != null)
+                    {
+                        // 合并区域:扩展物体边界并更新状态
+                        matched.MinStartCol = Math.Min(matched.MinStartCol, region.Start);
+                        matched.MaxEndCol = Math.Max(matched.MaxEndCol, region.End);
+                        matched.Area += region.End - region.Start + 1;
+                        matched.LastSeenLine = currentLine;
+                        matched.RowsData.Add(new RowStartEndCol
+                        {
+                            StartCol = region.Start,
+                            EndCol = region.End,
+                            RowsCol = currentLine,
+                        });
+                    }
+                    else
+                    {
+                        // 创建新物体(首次出现的区域)
+                        activeObjects.Add(new ActiveObjectClass
+                        {
+                            MinStartCol = region.Start,
+                            MaxEndCol = region.End,
+                            StartLine = currentLine,
+                            LastSeenLine = currentLine,
+                            LastSeenLineStartCol = region.Start,
+                            LastSeenLineEndCol = region.End,
+                            StartCheckTime = DateTime.Now,
+                            Area = region.End - region.Start + 1,
+                            ImageWidth = IdentifyImageWidth,
+                            RowsData = new List<RowStartEndCol> {
+                                new RowStartEndCol {
+                                    StartCol = region.Start,
+                                    EndCol = region.End,
+                                    RowsCol = currentLine,
+                                }
+                            }
+                        });
+                    }
+                }
+            }); // 延迟
+            Console.WriteLine($"Operation {i} completed");
+            return $"Result {i}";
+        }
         #endregion
 
         #region 线程方法

+ 37 - 33
TestWork.DLL/SqlDataClass/ActionMesSqliteDataClass.cs

@@ -10,6 +10,7 @@ namespace CCDCount.DLL.SqlDataClass
     {
         private string DatabaseFile;
         private readonly string _connectionString;
+        private object locker = new object();
 
         public ActionMesSqliteDataClass(string dbPath)
         {
@@ -86,15 +87,17 @@ namespace CCDCount.DLL.SqlDataClass
         // 插入ActiveObjectClass对象及其关联数据
         public void InsertActiveObject(ActiveObjectClass activeObject)
         {
-            using (var conn = new SQLiteConnection(_connectionString))
+            lock (locker)
             {
-                conn.Open();
-                using (var transaction = conn.BeginTransaction())
+                using (var conn = new SQLiteConnection(_connectionString))
                 {
-                    try
+                    conn.Open();
+                    using (var transaction = conn.BeginTransaction())
                     {
-                        // 插入主表数据
-                        const string insertActiveObject = @"
+                        try
+                        {
+                            // 插入主表数据
+                            const string insertActiveObject = @"
                         INSERT INTO ActiveObject (
                             Num, MinStartCol, MaxEndCol, LastSeenLineStartCol, 
                             LastSeenLineEndCol, StartLine, LastSeenLine, 
@@ -107,36 +110,37 @@ namespace CCDCount.DLL.SqlDataClass
                             @ChannelNO, @ImageWidth, @StateCode
                         ); SELECT last_insert_rowid();";
 
-                        using (var cmd = new SQLiteCommand(insertActiveObject, conn))
-                        {
-                            cmd.Parameters.AddWithValue("@Num", activeObject.Num);
-                            cmd.Parameters.AddWithValue("@MinStartCol", activeObject.MinStartCol);
-                            cmd.Parameters.AddWithValue("@MaxEndCol", activeObject.MaxEndCol);
-                            cmd.Parameters.AddWithValue("@LastSeenLineStartCol", activeObject.LastSeenLineStartCol);
-                            cmd.Parameters.AddWithValue("@LastSeenLineEndCol", activeObject.LastSeenLineEndCol);
-                            cmd.Parameters.AddWithValue("@StartLine", activeObject.StartLine);
-                            cmd.Parameters.AddWithValue("@LastSeenLine", activeObject.LastSeenLine);
-                            cmd.Parameters.AddWithValue("@StartCheckTime", activeObject.StartCheckTime.ToString("o"));
-                            cmd.Parameters.AddWithValue("@EndCheckTime", activeObject.EndCheckTime.ToString("o"));
-                            cmd.Parameters.AddWithValue("@Area", activeObject.Area);
-                            cmd.Parameters.AddWithValue("@MaxLength", activeObject.MaxLength);
-                            cmd.Parameters.AddWithValue("@ChannelNO", activeObject.ChannelNO);
-                            cmd.Parameters.AddWithValue("@ImageWidth", activeObject.ImageWidth);
-                            cmd.Parameters.AddWithValue("@StateCode", activeObject.StateCode);
+                            using (var cmd = new SQLiteCommand(insertActiveObject, conn))
+                            {
+                                cmd.Parameters.AddWithValue("@Num", activeObject.Num);
+                                cmd.Parameters.AddWithValue("@MinStartCol", activeObject.MinStartCol);
+                                cmd.Parameters.AddWithValue("@MaxEndCol", activeObject.MaxEndCol);
+                                cmd.Parameters.AddWithValue("@LastSeenLineStartCol", activeObject.LastSeenLineStartCol);
+                                cmd.Parameters.AddWithValue("@LastSeenLineEndCol", activeObject.LastSeenLineEndCol);
+                                cmd.Parameters.AddWithValue("@StartLine", activeObject.StartLine);
+                                cmd.Parameters.AddWithValue("@LastSeenLine", activeObject.LastSeenLine);
+                                cmd.Parameters.AddWithValue("@StartCheckTime", activeObject.StartCheckTime.ToString("o"));
+                                cmd.Parameters.AddWithValue("@EndCheckTime", activeObject.EndCheckTime.ToString("o"));
+                                cmd.Parameters.AddWithValue("@Area", activeObject.Area);
+                                cmd.Parameters.AddWithValue("@MaxLength", activeObject.MaxLength);
+                                cmd.Parameters.AddWithValue("@ChannelNO", activeObject.ChannelNO);
+                                cmd.Parameters.AddWithValue("@ImageWidth", activeObject.ImageWidth);
+                                cmd.Parameters.AddWithValue("@StateCode", activeObject.StateCode);
 
-                            // 获取新插入的主键ID
-                            var activeObjectId = Convert.ToInt32(cmd.ExecuteScalar());
+                                // 获取新插入的主键ID
+                                var activeObjectId = Convert.ToInt32(cmd.ExecuteScalar());
 
-                            // 插入关联的RowData
-                            InsertRowData(conn, activeObjectId, activeObject.RowsData);
-                        }
+                                // 插入关联的RowData
+                                InsertRowData(conn, activeObjectId, activeObject.RowsData);
+                            }
 
-                        transaction.Commit();
-                    }
-                    catch
-                    {
-                        transaction.Rollback();
-                        throw;
+                            transaction.Commit();
+                        }
+                        catch
+                        {
+                            transaction.Rollback();
+                            throw;
+                        }
                     }
                 }
             }

+ 1 - 0
TestWork.MODEL/CCDCount.MODEL.csproj

@@ -54,6 +54,7 @@
     <Compile Include="ShuLiModel\ActiveObjectClass.cs" />
     <Compile Include="ShuLiModel\ActiveObjectEventArgsClass.cs" />
     <Compile Include="ConfigModel\ShuLiConfigClass.cs" />
+    <Compile Include="ShuLiModel\ValidRegionModelClass.cs" />
     <Compile Include="SqlDataModel\ErroeMesDataModelClass.cs" />
     <Compile Include="SqlDataModel\ErrorMesDataEventModelClass.cs" />
     <Compile Include="SqlDataModel\UserMesDataModelClass.cs" />

+ 1 - 1
TestWork.MODEL/ConfigModel/ShuLiConfigClass.cs

@@ -20,7 +20,7 @@
         /// <summary>
         /// 允许物体中断的最大连续行数
         /// </summary>
-        public int MAX_GAP { get; set; } = 2;
+        public int MAX_GAP { get; set; } = 1;
         /// <summary>
         /// 单个物体允许的最大高度
         /// </summary>

+ 14 - 0
TestWork.MODEL/ShuLiModel/ValidRegionModelClass.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CCDCount.MODEL.ShuLiModel
+{
+    public class ValidRegionModelClass
+    {
+        public int Start { get; set;}
+        public int End { get; set; }
+    }
+}