如题,这个问题本人已经纠结了快三个工作日了。本人不同WinFrom程序一起动就会开启10个线程,并发对10张图片进行算法处理,问题是只要程序一起动就会报“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”异常。
本人试过将8个线程停掉,只开两个,发现没有问题,开三个四个偶尔会出问题….反正10个一个开是一定会报异常的。开起来好像是线程开太多CPU反应不过来导致的问题,可是CPU反应不过来就会报“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”异常吗?本人在网上查了查这种多线程并发报异常的问题很可能是线程与线程间有共享资源导致的问题,本人倒觉得没有共享什么资源啊,各位高手帮本人看看本人的线程处理函数里面存在共享资源吗?
线程1的线程处理函数:
本人试过将8个线程停掉,只开两个,发现没有问题,开三个四个偶尔会出问题….反正10个一个开是一定会报异常的。开起来好像是线程开太多CPU反应不过来导致的问题,可是CPU反应不过来就会报“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”异常吗?本人在网上查了查这种多线程并发报异常的问题很可能是线程与线程间有共享资源导致的问题,本人倒觉得没有共享什么资源啊,各位高手帮本人看看本人的线程处理函数里面存在共享资源吗?
线程1的线程处理函数:
private void AlgorithmHandlerThreadMethod1() { Bitmap test1 = new Bitmap("E:\和路雪\和路雪 2014-7-09\TestControl\蛋筒\1.jpg"); ProjectCalculation testHalcon = new ProjectCalculation(); ConesInspectionHalcon01 ParameterIn = new ConesInspectionHalcon01(); ConesInspectionHalcon01 ParameterOut = new ConesInspectionHalcon01(); ParameterIn.AreaAddSet = 50000; ParameterIn.MaxAreaSet = 350; ParameterIn.MaxEdgeSet = 150; ParameterIn.AreaCutSet = 40000; while (true) { if (threadFlag) { long start = DateTime.Now.Ticks; ProjectCalculation.ConesInspectionHalcon01(test1, ParameterIn, out ParameterOut); Thread.Sleep(1000); } } }
线程2的线程处理函数:
private void AlgorithmHandlerThreadMethod2() { Bitmap test2 = new Bitmap("E:\和路雪\和路雪 2014-7-09\TestControl\蛋筒\2.jpg"); ProjectCalculation testHalcon = new ProjectCalculation(); ConesInspectionHalcon01 ParameterIn = new ConesInspectionHalcon01(); ConesInspectionHalcon01 ParameterOut = new ConesInspectionHalcon01(); ParameterIn.AreaAddSet = 50000; ParameterIn.MaxAreaSet = 350; ParameterIn.MaxEdgeSet = 150; ParameterIn.AreaCutSet = 40000; while (true) { if (threadFlag) { long start = DateTime.Now.Ticks; ProjectCalculation.ConesInspectionHalcon02(test2, ParameterIn, out ParameterOut); Thread.Sleep(1000); } } }
线程3、4….10的线程处理函数一次类推。
ConesInspectionHalcon01函数:
public static void ConesInspectionHalcon01(Bitmap bitmap, ConesInspectionHalcon01 ParameterIn, out ConesInspectionHalcon01 ParameterOut) { Bitmap bm = (Bitmap)bitmap.Clone(); Stopwatch sw = new Stopwatch(); sw.Start(); HDevelopExport he = new HDevelopExport(); BitmapData bd = bm.LockBits(new Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); IntPtr intp = bd.Scan0; Bitmap b1 = new Bitmap(bm.Width, bm.Height, PixelFormat.Format8bppIndexed); Bitmap b2 = new Bitmap(bm.Width, bm.Height, PixelFormat.Format8bppIndexed); Bitmap b3 = new Bitmap(bm.Width, bm.Height, PixelFormat.Format8bppIndexed); BitmapData bd1 = b1.LockBits(new Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); BitmapData bd2 = b2.LockBits(new Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); BitmapData bd3 = b3.LockBits(new Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); IntPtr intp1 = bd1.Scan0; IntPtr intp2 = bd2.Scan0; IntPtr intp3 = bd3.Scan0; unsafe { Work.Correction.RGBToChannel(intp, intp1, intp2, intp3, bm.Width, bm.Height); } sw.Stop(); string tmp = sw.ElapsedMilliseconds.ToString(); Console.WriteLine(tmp); sw.Reset(); // label2.Text = tmp; bm.UnlockBits(bd); HImage h1 = new HImage(); HImage h2 = new HImage(); HImage h3 = new HImage(); HTuple AreaCut, MaxArea, MaxEdge, AreaAdd; HTuple hv_Gray, hv_Deviation; sw.Start(); h1.GenImage1("byte", bm.Width, bm.Height, intp1); h2.GenImage1("byte", bm.Width, bm.Height, intp2); h3.GenImage1("byte", bm.Width, bm.Height, intp3); sw.Stop(); tmp = sw.ElapsedMilliseconds.ToString(); Console.WriteLine(tmp); sw.Reset(); try { sw.Start(); he.ScaleCircle(h1, h2, h3, out AreaAdd, out MaxArea, out MaxEdge, out AreaCut, out hv_Gray, out hv_Deviation); sw.Stop(); tmp = sw.ElapsedMilliseconds.ToString(); Console.WriteLine(tmp); sw.Reset(); } catch (Exception ex) { AreaAdd = 1000000; MaxArea = 1000000; MaxEdge = 1000000; AreaCut = 1000000; hv_Gray = 0; hv_Deviation = 0; } if (hv_Gray.D <= 30) { AreaAdd = 1000000; MaxArea = 1000000; MaxEdge = 1000000; AreaCut = 1000000; } ParameterOut = new ConesInspectionHalcon01(); // ParameterOut=ParameterIn; ParameterOut.CurrentAreaAdd = AreaAdd; ParameterOut.CurrentAreaCut = AreaCut; ParameterOut.CurrentMaxEdge = MaxEdge; ParameterOut.CurrentMaxArea = MaxArea; ParameterOut.hv_Gray = hv_Gray; // ParameterOut.hv_Deviation = hv_Deviation; h1.Dispose(); h2.Dispose(); h3.Dispose(); b1.UnlockBits(bd1); b2.UnlockBits(bd2); b3.UnlockBits(bd3); b1.Dispose(); b2.Dispose(); b3.Dispose(); if (ParameterOut.CurrentAreaAdd > ParameterIn.AreaAddSet || ParameterOut.CurrentMaxArea > ParameterIn.MaxAreaSet || ParameterOut.CurrentMaxEdge > ParameterIn.MaxEdgeSet || ParameterOut.CurrentAreaCut > ParameterIn.AreaCutSet) { ParameterOut.Result = false; ParameterOut.Index = 10; } else { ParameterOut.Result = true; ParameterOut.Index = 11; } //ParameterOut.Index = ParameterIn.Index; if (bm != null) { bm.Dispose(); } }
ConesInspectionHalcon02
ConesInspectionHalcon03 …ConesInspectionHalcon10和ConesInspectionHalcon01内容是一样的。
解决方案
40
首先 GDI+ 对多线程支持就不好,一般的建议是,假如需要通过 GDI+ 并发进行图像处理,不要使用多线程,而是使用多进程方式。其次假如还使用了第三方库(包括托管的和非托管的),它们也必须线程安全才行。
GDI+ 的毛病非常多,长期重要的任务尽量不要依赖它,而是使用其它图像处理库。
GDI+ 的毛病非常多,长期重要的任务尽量不要依赖它,而是使用其它图像处理库。