SpriteBatch: "Begin cannot be called again until End has been successfully called."
Asked Answered
P

5

7

So I started up my current project, and the first thing I did was run it, and it gave me the above exception. It was running fine last night. This is all the code in my Draw event. spriteBatch.Begin doesn't appear anywhere else in the project. Removing the Begin here causes the spriteBatch.Draw to throw an exception, putting a spriteBatch.End right before the begin also throws an exception. I'm at a loss as to what's wrong and how to fix this.

GraphicsDevice.Clear(Color.CornflowerBlue);

spriteBatch.Begin();
spriteBatch.Draw(background, Vector2.Zero, Color.White);

player.Draw(spriteBatch);
level1.Draw(spriteBatch);

spriteBatch.End();

base.Draw(gameTime);
Priapus answered 21/11, 2012 at 21:58 Comment(2)
For a complete story, could you provide the draw methods for player and level1? As the problem might be caused in those methods.Likable
2 Posibilities : 1| either in player.draw or level1.draw you call spritebatch.begin() 2| spirteBatch.End() doesn't get called because you don't reach it.Groth
I
1

Well I need to see your levek1.Draw and player.Draw for my info, but what im expecting this. In one of you methods, you are calling spriteBatch.Begin(), You MUST call End() before calling this.

So if your player class draw method looks like this

Draw(Spritebatch spriteBatch)
{
spriteBatch.Begin();
spriteBatch.Draw(PlayerSprite,PlayerPosition, etc);
spriteBatch.End();
}

You need to remove the Begin and End calls, because they were already called by the parent method.

EDIT: Didn't read clearly, I see you belive that this is not the problem, But we need to see the other methods to figure out the problem.

Infirmity answered 21/11, 2012 at 23:0 Comment(0)
D
1

It's possible that one of your draw calls is throwing an exception. This would throw you out of the method without calling spriteBatch.End(), and then the next time through, you'd get an exception on spriteBatch.Begin(). (Although I would wonder why the first exception didn't end your program, but the second one did.)

If that is the issue, one solution would be to wrap the draw calls in a try/finally block:

spriteBatch.Begin();
spriteBatch.Draw(background, Vector2.Zero, Color.White);

try {
   player.Draw(spriteBatch);
   level1.Draw(spriteBatch);
} finally {
   spriteBatch.End();
}

Another possibility is that you are actually accidentally calling spriteBatch.Begin() twice. Personally I avoid doing this by wrapping the SpriteBatch object in a different class.

Ex:

internal sealed class DrawParams
{
   private SpriteBatch mSpriteBatch;
   private bool mBegin;

   /// <summary>Calls SpriteBatch.Begin if the begin value is true. Always call this in a draw method; use the return value to determine whether you should call EndDraw.</summary>
   /// <returns>A value indicating whether or not begin was called, and thus whether or not you should call end.</returns>
   public bool BeginDraw()
   {
      bool rBegin = mBegin;

      if (mBegin)
      {
         mSpriteBatch.Begin();
         mBegin = false;
      }

      return rBegin;
   }

   /// <summary>Always calls SpriteBatch.End. Use the return value of BeginDraw to determine if you should call this method after drawing.</summary>
   public void EndDraw()
   {
      mSpriteBatch.End();
   }
}
Dyslexia answered 22/11, 2012 at 12:19 Comment(0)
D
1

Had this exact problem myself, and none of the suggestions worked on here. Finally, I realised that within my Begin / End section, I was awaiting an asynchronous method.

Having realised that this would potentially then restart the method before finishing, I simply added a bool isDrawing variable and checked it before drawing.

HTH

Deeprooted answered 18/12, 2013 at 8:31 Comment(0)
M
1

If you exit the spritebatch while it's busy drawing, you will get the same problem. For example, when you leave the screen from another event, for example, a timer.

In my case, i've declared a private variable which stores whether the SpriteBatch was interrupted,

private bool _spriteBatchInterrupted = false;

and check it while the SpriteBatch is continually drawing,

    Game.SpriteBatch.Begin();
    if (_spriteBatchInterrupted)
    {
        Game.SpriteBatch.End();
        return;
    }...

Then set the variable in the other event, for example, the timer lapsed event

private void CountdownTimer_Elapsed(object sender, ElapsedEventArgs e)
{
   _spriteBatchInterrupted = true;
   NavigateTask();
}

     
Mannish answered 23/7, 2021 at 6:33 Comment(0)
M
0

Press ctrl+F and select Entire Solution, look for spriteBatch.Begin() and remove it where it doesn't belong. I suspect you may have extra copies in your player or level draw calls.

Also be sure you're using the right variable for your sprite batch, it may be called SpriteBatch, with first letter capitalized.

Anyway, you can try removing (comment them with //) all spritebatch calls from your project and see if it still throws an exception.

Maharanee answered 21/11, 2012 at 23:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.