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"错误。
你能解释一下它为什么这么做吗,以及建议的解决方法是什么吗?
来自类似的问题:https://stackoverflow.com/a/1852451/1364848
GDI+内部有一个锁,阻止两个线程同时访问位图。这不是一个阻塞类型的锁,它是一个"程序员做错了什么,我会抛出一个异常"类型的锁。
您的计时器位于不同的线程上,并且两者都使用SetPixel访问位图。
您可以使用锁定同步对位图的访问http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx