InvalidOperationException-修改位图时,对象当前正在其他地方使用

本文关键字:其他 方使用 位图 修改 对象 InvalidOperationException- | 更新日期: 2023-09-27 18:00:10

我知道这个主题上有很多问题,但我发现没有一个对我有帮助。我对线程不太熟悉。

我正在创建一个太空入侵者游戏,使用pull MVC架构。

也就是说,View被传递了游戏的一个实例,并定期调用游戏的getMainSprite()方法,并显示该方法。

同时,游戏在自己的计时器上运行,并定期更新自己的主精灵。

剥离代码:

太空入侵者.cs(主要游戏类);

    private void timerTick(object source, ElapsedEventArgs e)
    {
        mainSprite.updateWithSprite(0, 0, anim); //Anim is an animated sprite which we're displaying for now
    }

精灵.cs:

    //*When we want to update a sprite, we pass in the sprite we want to update it with
and it updates all the pixels*/
    public void updateWithSprite(int x, int y, Sprite sprite)
    {
        Bitmap sprBitmap = sprite.getBitmap();             
        for (int i = 0; i < sprBitmap.Width; i++)
        {
            for (int j = 0; j < sprBitmap.Height; j++)
            {    
                this.bitmap.SetPixel(x + i, y + j, sprBitmap.GetPixel(i, j));
            }
        }
    }

Form1.cs

    private void timerTick(object source, EventArgs e)
    {
        this.refreshView(this.game.getMainSprite());
    }
    private void refreshView(Sprite gs)
    {
                this.currentSprite = gs;
                this.panel1.Refresh();
   }

    private void drawSprite(Graphics canvas, Sprite sprite){
        Bitmap bitmap = (Bitmap)sprite.getBitmap();
        //lock(bitmap)
        canvas.DrawImage(bitmap, new Rectangle(0, 0, MAIN_SPRITE_WIDTH*PIXEL_WIDTH, MAIN_SPRITE_HEIGHT*PIXEL_WIDTH)); 

    }
    private void panel1_Paint(object sender, PaintEventArgs e)
    {
        this.drawSprite(canvas, currentSprite);
    }

现在,当它执行updateSprite/setPixel方法时,它会随机向我抛出"InvalidOperationException-object current in use otherwhere"错误。

你能解释一下它为什么这么做吗,以及建议的解决方法是什么吗?

InvalidOperationException-修改位图时,对象当前正在其他地方使用

来自类似的问题:https://stackoverflow.com/a/1852451/1364848

GDI+内部有一个锁,阻止两个线程同时访问位图。这不是一个阻塞类型的锁,它是一个"程序员做错了什么,我会抛出一个异常"类型的锁。

您的计时器位于不同的线程上,并且两者都使用SetPixel访问位图。

您可以使用锁定同步对位图的访问http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx