Code Bye

关于Winform的内存使用问题

目的:
游戏简单的脚本  实现2个号互相刷级
Winform很少接触 但想试着接触学习一下
在网上找了一些API的使用方法 也都没什么问题
然后使用了网上找来的找图方法  问题来了. 运行1个半小时左右以后内存就炸了
CPU I7 4790K 内存16G DDR3
但本人在任务管理器里看内存使用占用了很少一部分 几乎可以忽略不计
但360加速球里面显示了占用百分之80-90
本人觉得可能是哪个地方没控制好 没释放
目前流程
1.用Thread.Timer1来控制截图、找图 以及判断能否触发一些动作
2.用Thread.Timer2来控制键盘按键
找图方法:
 /// <summary>
        /// 修改后的查找图片,不能镂空 
        /// </summary>
        /// <param name="subPic">小图路径</param>
        /// <param name="parPic">大图bitmap</param>
        /// <param name="searchRect">假如为empty,则默认查找整个图像</param>
        /// <param name="errorRange">容错,单个色值范围内视为正确0~255</param>
        /// <param name="matchRate">图片匹配度,默认90%</param>
        /// <param name="isFindAll">能否查找全部相似的图片</param>
        /// <returns>返回查找到的图片的中心点坐标</returns>
        public static List<System.Drawing.Point> FindPicture(string subPic, Bitmap parPic, System.Drawing.Rectangle searchRect, byte errorRange, double matchRate = 0.9, bool isFindAll = false)
        {
            List<System.Drawing.Point> ListPoint = new List<System.Drawing.Point>();
            var subBitmap = new Bitmap(subPic);
            var parBitmap = new Bitmap(parPic);
            int subWidth = subBitmap.Width;
            int subHeight = subBitmap.Height;
            int parWidth = parBitmap.Width;
            int parHeight = parBitmap.Height;
            if (searchRect.IsEmpty)
            {
                searchRect = new System.Drawing.Rectangle(0, 0, parBitmap.Width, parBitmap.Height);
            }
            var searchLeftTop = searchRect.Location;
            var searchSize = searchRect.Size;
            System.Drawing.Color startPixelColor = subBitmap.GetPixel(0, 0);
            var subData = subBitmap.LockBits(new System.Drawing.Rectangle(0, 0, subBitmap.Width, subBitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            var parData = parBitmap.LockBits(new System.Drawing.Rectangle(0, 0, parBitmap.Width, parBitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            var byteArrarySub = new byte[subData.Stride * subData.Height];
            var byteArraryPar = new byte[parData.Stride * parData.Height];
            Marshal.Copy(subData.Scan0, byteArrarySub, 0, subData.Stride * subData.Height);
            Marshal.Copy(parData.Scan0, byteArraryPar, 0, parData.Stride * parData.Height);
            var iMax = searchLeftTop.Y + searchSize.Height - subData.Height;//行
            var jMax = searchLeftTop.X + searchSize.Width - subData.Width;//列
            int smallOffsetX = 0, smallOffsetY = 0;
            int smallStartX = 0, smallStartY = 0;
            int pointX = -1; int pointY = -1;
            for (int i = searchLeftTop.Y; i < iMax; i++)
            {
                for (int j = searchLeftTop.X; j < jMax; j++)
                {
                    //大图x,y坐标处的颜色值
                    int x = j, y = i;
                    int parIndex = i * parWidth * 4 + j * 4;
                    var colorBig = System.Drawing.Color.FromArgb(byteArraryPar[parIndex + 3], byteArraryPar[parIndex + 2], byteArraryPar[parIndex + 1], byteArraryPar[parIndex]);
                    ;
                    if (ColorAEqualColorB(colorBig, startPixelColor, errorRange))
                    {
                        smallStartX = x - smallOffsetX;//待找的图X坐标
                        smallStartY = y - smallOffsetY;//待找的图Y坐标
                        int sum = 0;//全部需要比对的有效点
                        int matchNum = 0;//成功匹配的点
                        for (int m = 0; m < subHeight; m++)
                        {
                            for (int n = 0; n < subWidth; n++)
                            {
                                int x1 = n, y1 = m;
                                int subIndex = m * subWidth * 4 + n * 4;
                                var color = System.Drawing.Color.FromArgb(byteArrarySub[subIndex + 3], byteArrarySub[subIndex + 2], byteArrarySub[subIndex + 1], byteArrarySub[subIndex]);
                                sum++;
                                int x2 = smallStartX + x1, y2 = smallStartY + y1;
                                int parReleativeIndex = y2 * parWidth * 4 + x2 * 4;//比对大图对应的像素点的颜色
                                var colorPixel = System.Drawing.Color.FromArgb(byteArraryPar[parReleativeIndex + 3], byteArraryPar[parReleativeIndex + 2], byteArraryPar[parReleativeIndex + 1], byteArraryPar[parReleativeIndex]);
                                if (ColorAEqualColorB(colorPixel, color, errorRange))
                                {
                                    matchNum++;
                                }
                            }
                        }
                        if ((double)matchNum / sum >= matchRate)
                        {
                            //Console.WriteLine((double)matchNum / sum);
                            pointX = smallStartX + (int)(subWidth / 2.0);
                            pointY = smallStartY + (int)(subHeight / 2.0);
                            var point = new System.Drawing.Point(pointX, pointY);
                            if (!ListContainsPoint(ListPoint, point, 10))
                            {
                                ListPoint.Add(point);
                            }
                            if (!isFindAll)
                            {
                                goto FIND_END;
                            }
                        }
                    }
                    //小图x1,y1坐标处的颜色值
                }
            }
        FIND_END:
            searchRect = Rectangle.Empty;
            subBitmap.UnlockBits(subData);
            parBitmap.UnlockBits(parData);
            subBitmap.Dispose();
            parBitmap.Dispose();
            GC.Collect();
            return ListPoint;
        }
        #endregion
      
以下是本人在Timer中的使用方法 简单的贴上来了一个  然后判断数组里能否有值去做相应操作
pointList_IsHall_Small.AddRange(ImageHelper.FindPicture(Path + "\Pic\大厅内.bmp", Smallbmp, new Rectangle(450, 20, 50, 30), 60, 0.9, false));
                    pointList_MissionComplete_Small.AddRange(ImageHelper.FindPicture(Path + "\Pic\任务完成.bmp", Smallbmp, new Rectangle(475, 432, 40, 20), 60, 0.9, false));
解决方案

10

可以尝试用MemProfiler等工具来定位内存泄漏问题

10

低级粗暴的办法,把你用的对象都点一下,有Dispose没调用的那种都处理一下

60

Win32Api.DeleteDC(hscrdc);
改成ReleaseDC试试

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明关于Winform的内存使用问题