对象当前在别处使用。图片框

Object is currently used elsewhere. PictureBox

我试图在一个应用程序中实现 Langton 的 Ant 算法。它有 1 个按钮和 1 个图片框控件。这是代码:

    int x = 100, y = 100;
    int angle = 90;

    private void button1_Click(object sender, EventArgs e)
    {
        Bitmap resultImage = new Bitmap(pictureBox1.Width, pictureBox1.Height, PixelFormat.Format24bppRgb);
        for (int i = 0; i < resultImage.Height; i++)
        {
            for (int z = 0; z < resultImage.Width; z++)
            {
                resultImage.SetPixel(z, i, Color.White);
            }
        }
        pictureBox1.Image = resultImage;
        Thread t = new Thread(new ThreadStart(run));
        t.Start();
    }

    public void run()
    {
        while (true)
        {
            lock (pictureBox1.Image)
            {
                //Exception takes place here.
                Bitmap b = (Bitmap)pictureBox1.Image;
                string name = b.GetPixel(x, y).Name;
                if (b.GetPixel(x, y).Name == "ffffffff")
                {
                    angle -= 90;
                    b.SetPixel(x, y, Color.Black);
                }
                else
                {
                    angle += 90;
                    b.SetPixel(x, y, Color.White);
                }
                pictureBox1.Image = b;
                x += (int)Math.Cos(angle * Math.PI / 180);
                y += (int)Math.Sin(angle * Math.PI / 180);
            }
            Thread.Sleep(50);
        }
    }

run() 方法中,Bitmap b = (Bitmap)pictureBox1.Image; 处始终存在异常,它表示 InvalidOperatopnException: Object is currently in use elshere。我是否锁定图像并不重要。当我将间隔增加到 250 毫秒或以上时,不会发生异常

两件事:

  1. 您正在从另一个线程访问 WinForms UI 组件。 GUI 个组件只能从 UI 线程访问(甚至读取)。
  2. 您正在操纵 PictureBox 已经在使用的 Bitmap,您应该直接用新图像替换它,或者先使用 Clone 方法,然后重新分配,并且不要忘记旧位图的Dispose,如果有的话。

试试这个:

private void ButtonClick() {

    Thread thread = new Thread( this.BackgroundThread );
    thread.Start(); // ideally, replace this with the .NET Task library
}

private void BackgroundThread() {

    Bitmap bmp = new Bitmap( ... );
    // do bitmap pixel-setting here

    this.Invoke( () => {
        Bitmap old = this.pictureBox1.Image as Bitmap;
        this.pictureBox1.Image = bmp;
        if( old != null ) {
            old.Dispose();
        }
    } );
}

此外,请避免使用 GetPixelSetPixel,它们非常慢。而是这样做:

BitmapData data = bmp.LockBits();
Byte[] buffer = new Byte[ ... ];
Marshal.Copy( data.Scan0, buffer, ... );

// Manipulate raw pixel data contained in buffer here

bmp.UnlockBits( data );