Change your code so that before calling Invalidate on any of the three controls, you create the one shared bitmap buffer (conceivably as a static member of your control class), and then call Invalidate on each of the controls. Within the control's Paint event you can then use the static bitmap buffer, and it won't matter in which order the Paint events fire.
When you call Invalidate on a control, you're basically telling the OS to send a WM_PAINT message to that control. Because it's a Windows message, it's guaranteed to be delivered whenever Windows gets around to doing it. In your case, they're usually delivered in the order received, but sometimes they just won't be.
One other thing to consider with your code: when you place relatively complex drawing code inside your control's Paint event handler (or inside a method called directly from the Paint event handler), this code will execute whenever the control is invalidated for any reason, meaning that the code will run when you call Invalidate, but it will also run whenever another window is dragged over the control.
For complex, time-consuming graphics, it's always best to perform the complex rendering on a hidden buffer (a Bitmap or an invisible PictureBox or whatever), and then in the control's Paint event do a simple copy from the hidden buffer to the visible window (using Graphics.DrawImage or BitBlt or whatever).
This approach also allows you to avoid flicker, if you add a second buffer in between the buffer you draw on and the visible window (hence "double buffering"). After you complete drawing on the main buffer, you copy it onto the second buffer. In the control's Paint event, you copy from the second buffer onto the visible window.