奇怪的“;试图读取或写入受保护的存储器“;错误行为
本文关键字:存储器 受保护 错误 读取 | 更新日期: 2023-09-27 18:28:58
我的C#WinForms程序中有一个方法,它检查图像的X列是否有黑色像素。
static Boolean GetColumnState(Bitmap bmp, int x, int col)
{
BitmapData pixelData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),ImageLockMode.ReadOnly,PixelFormat.Format32bppArgb);
Boolean state = false;
unsafe
{
int* pData = (int*)pixelData.Scan0.ToPointer();
pData += x;
for (int i = 0; i < bmp.Height; ++i)
{
pData += bmp.Width;
if (Color.FromArgb(*pData) == Color.FromArgb(255, col, col, col)) // error here
{ state = true; break; }
}
}
bmp.UnlockBits(pixelData);
return state;
}
不幸的是,我得到了
"试图读取或写入受保护的内存"错误
在"(Color.FromArgb(*pData)==Color.FromArgb(255,col,col))"行
以下是我如何从不同的方法定义"col":
if (GetColumnState(b1, 0, 255) == false)
{ col = 255; }
else {col = 0;}
// more code + loops
GetColumnState(b1, i, col)
奇怪的是:只有当像素颜色定义为255(即黑色)时,我才会出错。。
您如何解释?请注意,我正在编写OCR程序,因此我加载了多个具有不同键值的词典。我在OCR过程中经常裁剪图像。我的幸运猜测是线程正在互相扰乱
现在,我已经找到了解决这个问题的方法,但价格是脚本执行总时间的+~150-200ms(我认为这是不必要的价格)。
通常我加载这样的字典:
Dictionary<string, Bitmap> lookup = new Dictionary<string, Bitmap>();
Bitmap l0 = new Bitmap(@"C:'xxx'0.bmp", true);
//+15 more
lookup.Add("0", l0);
//+15 more
Dictionary<string, Bitmap> lookup2 = new Dictionary<string, Bitmap>();
Bitmap nAa = new Bitmap(@"C:'yyy'Aa.bmp", true);
//+15 more
lookup2.Add("A", nAa);
//+15 more
为了解决这个问题,我必须为每个字典创建"void",并将它们加载到不同的线程中,如下所示:
void loadNumbers1()
{
lookup4 = new Dictionary<string, Bitmap>();
Bitmap sd = new Bitmap(@"C:'xxxxx'a.bmp", true);
//+15 more
lookup4.Add("0", s0);
//+15 more
}
void loadNumbers2()// 4, 5, 6,
{
//repeat
}
现在我们推出线程:
Thread tNum2= new Thread(new ThreadStart(loadNumbers2));
tNum2.Start();
Thread tNum3= new Thread(new ThreadStart(loadNumbers3));
tNum3.Start();
最后一步(如果没有此步骤程序,工作速度更快,但错误发生的频率更高):
tNum3.Join();
就是这样,现在我没有任何问题,但执行时间更长了。。关于如何在不使用多个线程的情况下以更简单的方式解决这个问题,有什么想法吗?在我的情况下,如果没有join(),我将获得5-100ms的字典加载时间,如果有join(,则最长可达300ms。无线程-最多180个(如果没有发生错误)。
抱歉发布时间过长
编辑:(永久修复)
static unsafe Boolean GetColumnState(Bitmap bmp, int x, int col)
{
BitmapData pixelData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),ImageLockMode.ReadOnly,PixelFormat.Format32bppArgb);
Boolean state = false;
unsafe
{
byte[] buffer = new byte[pixelData.Height * pixelData.Stride];
Marshal.Copy(pixelData.Scan0, buffer, 0, buffer.Length);
for (int i = 0; i < pixelData.Height - 1; ++i)
{
byte red = buffer[i * pixelData.Stride + 4 * x + 2];
if (red == col)
{ state = true; break; }
}
}
bmp.UnlockBits(pixelData);
return state;
}
我不明白指针有什么错,但字节的工作原理很好@tia谢谢你指出我的问题。
有人知道为什么多线程会减慢字典加载时间而不是加快它吗
如果我正确理解代码,循环
for (int i = 0; i < bmp.Height; ++i)
{
pData += bmp.Width;
if (Color.FromArgb(*pData) == Color.FromArgb(255, col, col, col)) // error here
{ state = true; break; }
}
不正确。指针应该在迭代结束时递增,否则您将跳过第一行扫描并溢出读取位图缓冲区。