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

时间:2014-04-26 08:00:22

标签: c# asp.net-mvc multithreading exception bitmap

我知道关于这个问题有很多问题,但我发现它们都没有帮助我从我所处的地方。我对线程不太熟悉。

我使用拉式MVC架构创建了一个太空入侵者游戏。

即 - 视图传递给游戏的一个实例,并定期调用游戏的getMainSprite()方法并显示该方法。

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

剥离代码:

SpaceInvaders.cs(主游戏类);

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

    }

Sprite.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方法时,它会随机抛出&#39; InvalidOperationException - 当前正在其他地方使用对象&#39;错误。

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

1 个答案:

答案 0 :(得分:0)

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

  

GDI +中存在一个锁定,阻止两个线程在同一&gt;时间访问位图。这不是一种阻塞的锁,它是一个&#34;程序员做错了什么,我会抛出异常&#34;锁定。

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

您可以使用锁定http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx

来同步对位图的访问权限