C# “奇怪”;试图读取或写入受保护内存“;错误行为

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);

我的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;
    }
奇怪的是:只有当像素颜色定义为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; }
}