简体   繁体   中英

Sleep only working in debug mode, and not release mode (Embarcadero C++ Builder)

I am using Embarcadero C++ Builder (an engineer not programmer)

I find the Sleep function is only working for me in debug mode and not in release mode. I see references in StackOverFlow not to use Sleep, and rather to use TTimer.

I simply want my app to pause for a few seconds between drawing objects as per the Sleep(500); in the code below, so that I can see each object being drawn and can check they are correct, else it happens to fast to check.

DrawSelectedShape(k,Side,AddOrDeduct,Color); in the below code, is the process that needs pausing

for (int n=0; n<LiquidLoads->TankBasicData->NoLiquidTypes; ++n){
  for (int m=0; m<LiquidLoads->TankBasicData->NumberOfTanks[n]; ++m)
  {
    for (int l=1; l<LongStrengths->TotalNumberOfParts+1; ++l)
     {
       if (LiquidLoads->TankHeaderArray[n][m]->GhsName == LongStrengths->PartHeader[l]->PartName)
       {

         for (int j=0; j<LongStrengths->PartHeader[l]->NoOfComponents; ++j)
         {
            int k = LongStrengths->PartData[l][j]->ShapeNumber;
            int Side = LongStrengths->PartData[l][j]->Side;
            float AddOrDeduct = LongStrengths->PartData[l][j]->Effectiveness;
            AnsiString Color = LiquidLoads->TankBasicData->LiquidTypeColor[n];
            DrawSelectedShape(k,Side,AddOrDeduct,Color);

            Canvas->TextOut(1200, 300+(n*25),LiquidLoads->TankBasicData->LiquidType[n]);
            Sleep(300);
         }
       break;
       }
   }
}  }

The above code works perfectly in debug mode, but in release mode, it works fine through the first few shapes being drawn to canvas, then you get a spinning wheel mouse cursor for a while followed by a blank canvas.

So I am looking for an alternative to Sleep.

When using a TTimer (no experience) one would use the OnTimer event, and place code that runs repeatedly in the event with a delay related to the Timer1 Interval, which is not quite the same as just looking for a few seconds delay in the middle of a for-loop

This is how my rendering looks like:

动画

Any advise, most appreciated.

well from the video you posted its clear animation using timer is the way to go...

From your description You should have some value ix for each visible object on your ship. Telling the layer or rendering order of the object.

So add a render_ix value to your rendering code (either global or a member of the form where are you rendering) then recode your draw routine to this:

int render_ix=0; // order/layer number for object to render up to

void draw()
 {
 // here clear&render background
 for (int i=0;i<objects;i++)
  if (object[i].ix<=render_ix)
   object[i].draw(); // render i-th object
 // here render HUD
 }

now just somwhere in your timer with desired interval

void OnTimerAnimation()
 {
 render_ix++;
 if (render_ix>=objects) render_ix=0;
 // here force repaint either by calling Paint, Refresh,Update ... or what ever way you are using
 }

You can also change the render_ix by scroll bar or programaticaly. As you can see no Sleep or Delay is needed hence no blocking of execution.

If your rendering is not order of object based but radher by some filtering than just change the render_ix with the variable you are filtering. This way you can nest more variables together (Volume, mass , position...) into nested if statements.

Another but very useful scheme is to use selections. So create a list of object indexes to render... and render/highlight only those that are present in the list. That is very useful for mouse selections and operation with more containers at once.

To avoid the for loops and if statements, that was part of the process of drawing to the canvas using the Sleep method to pause the loops, I now first had to generate a render sequence to a Struct, that I could then use with a single sequential counter in TTimer

as below

//---------------------------------------------------------------------------
void __fastcall TShipGraphic::DrawSelectedTanksBtnClick(TObject *Sender)
{
    GenerateRenderSequence();
    Timer1->Interval = StrToInt(Edit1->Text);
    CloseButton->Enabled = false;
    render_ix=0; //Initialised globally

     Timer1->Enabled = true;

}
//---------------------------------------------------------------------------
void __fastcall TShipGraphic::Timer1Timer(TObject *Sender)
{
 render_ix++;
 Timer1->Interval = StrToInt(Edit1->Text);
 if (render_ix<=TankShapeCounter)
 {
    DrawSelectedComponentShape(render_ix); // render i-th object
    Canvas->Refresh();
 }
 else
 {
   Timer1->Enabled = false;
   CloseButton->Enabled = true;
 }
}
//---------------------------------------------------------------------------
void TShipGraphic::GenerateRenderSequence()
{
   TankShapeCounter = 0;

  for (int n=0; n<LiquidLoads->TankBasicData->NoLiquidTypes; ++n)
  {
    if ((CheckListBox1->Checked[n]) || (CheckListBox1->Checked[LiquidLoads->TankBasicData->NoLiquidTypes]))
    {
      for (int m=0; m<LiquidLoads->TankBasicData->NumberOfTanks[n]; ++m)
      {

        for (int l=1; l<LongStrengths->TotalNumberOfParts+1; ++l)
         {
           if (LiquidLoads->TankHeaderArray[n][m]->GhsName == LongStrengths->PartHeader[l]->PartName)
           {

             for (int j=0; j<LongStrengths->PartHeader[l]->NoOfComponents; ++j)
             {
                ++TankShapeCounter;
                int k = LongStrengths->PartData[l][j]->ShapeNumber;
                int Side = LongStrengths->PartData[l][j]->Side;
                float AddOrDeduct = LongStrengths->PartData[l][j]->Effectiveness;
                AnsiString Color = LiquidLoads->TankBasicData->LiquidTypeColor[n];
                RenderSequence[TankShapeCounter]->ShapeNumber = k;
                RenderSequence[TankShapeCounter]->Side = Side;
                RenderSequence[TankShapeCounter]->AddOrDeduct = AddOrDeduct;
                RenderSequence[TankShapeCounter]->Color = Color;
             }
           break;
           }
         }
      }
    }
  }
}
//---------------------------------------------------------------------------

I wanted to use @Spectre's neat animated gif method to show the result, but my Game Bar is too temperamental to capture the screen animation to a video. "Win G" to activate the Game Bar is doing nothing.

Thanks to Remy and Spektre for the valuable advise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM