C# “奇怪”;试图读取或写入受保护内存“;错误行为
我的C#WinForms程序中有一个方法,可以检查图像的X列是否有黑色像素C# “奇怪”;试图读取或写入受保护内存“;错误行为,c#,multithreading,dictionary,C#,Multithreading,Dictionary,我的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);
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;
}
奇怪的是:只有当像素颜色定义为255(即黑色)时,我才会出错
你如何解释这一点?请注意,我正在编写一个OCR程序,因此我加载了多个具有不同键值的词典。我在OCR期间裁剪了很多图像。
我的幸运猜测是线程正在互相弄乱。
现在,我找到了解决这个问题的方法,但代价是总脚本执行时间的+~150-200毫秒(我认为这是不必要的代价)
通常,我加载的字典如下所示:
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 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
}
最后一步(没有此步骤,程序运行更快,但错误发生的频率更高):
就是这样,现在我没有任何问题,但执行时间更长。。关于如何更简单地解决这个问题,而不使用多个线程,有什么想法吗?在我的例子中,如果没有join(),我将获得5-100ms的字典加载时间,而join()的加载时间最长可达300ms。无线程-最多180个(如果没有发生错误)
很抱歉发了这么长的邮件
编辑:(永久修复)
静态不安全布尔GetColumnState(位图bmp、int x、int col)
{
BitmapData pixelData=bmp.LockBits(新矩形(0,0,bmp.Width,bmp.Height),ImageLockMode.ReadOnly,PixelFormat.Format32bppArgb);
布尔状态=假;
不安全的
{
字节[]缓冲区=新字节[pixelData.Height*pixelData.Stride];
Marshal.Copy(pixelData.Scan0,buffer,0,buffer.Length);
对于(int i=0;i
我不明白指针到底出了什么问题,但字节工作得很好@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; }
}
for(int i=0;i
这是不对的。指针应该在迭代结束时递增,否则您将跳过第一个扫描行并溢出读取位图缓冲区。好的,我必须完全删除指针,因为我根本不理解它们,而使用字节[]。。请参见编辑。不管怎样,为什么线程处理会大大降低执行时间?
Thread tNum2= new Thread(new ThreadStart(loadNumbers2));
tNum2.Start();
Thread tNum3= new Thread(new ThreadStart(loadNumbers3));
tNum3.Start();
tNum3.Join();
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;
}
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; }
}