title: Drawing to main form canvas from a non-main thread
body: <p>I am trying to make an arcade game for my school project. The basic idea is to do all the math and drawing in other thread than the main, and to use the main thread only for input routines. Drawing is done by a procedure saved in an external unit, and is done by creating a bitmap, then drawing parts of the environment on the bitmap and finally dawing the bitmap on the main form's canvas. When I finished the drawing procedure, I tried to run it from the main thread, and managed to make everythink work as expected (except for the fact that the whole application window was frozen, but since the main thread was working without stopping, sommething like that was expected). Then i tried to put the procedure in other thread, and it stopped working (it didnt draw a single thing despite debug routines reporting that the procedure was repeatedly executed). After a few added and then deleted debug routnes, it started to work for no apparent reason, but not reliably. in about 80% of cases it runs smoothly, but in the rest it stops after ten to thirty frames, sometimes even not draving some of the environment parts in the last frame where it gets stuck.</p>
  
  <p>The important part of the main form unit looks like this</p>
  
  <pre><code>procedure TForm1.Button1Click(Sender: TObject);
  
  begin
  running:=not running;
  if running then AppTheard.Create(false);
  end;
  
  Procedure AppTheard.execute;
  
  begin
   form1.Button1.Caption:='running';
   while running do begin view.nextframe; end;
   form1.Button1.Caption:='no longer running';
  
  end;
  </code></pre>
  
  <p>and the nextframe procedure in the other unit looks like this</p>
  
  <pre><code>     Camera = class
   owner:Tform;
   focus:GravityAffected;
   Walls:PBlankLevel;
   Creeps:MonsterList;
   FrameRateCap,lastframe:integer;
   Background:TBitmap;
   plocha:TBitmap;
   RelativePosY,RelativePosX:integer;
   constructor create(owner:Tform; focus:GravityAffected; Walls:PBlankLevel; Creeps:MonsterList; FrameRateCap:integer; background:TBitmap);
   procedure nextframe;
  end;    
  
  
  
   procedure camera.nextframe;
   var i,i1,top,topinfield, left,leftinfield: integer ;
  
    procedure Repair
        //some unimportant math here
  
    Procedure vykresli(co:vec);
     begin
     if co is gravityaffected then
      plocha.Canvas.Draw(co.PositionX*fieldsize+Gravityaffected(co).PosInFieldX-Left*fieldsize+leftinfield-co.getImgPosX,
       co.PositionY*fieldsize+Gravityaffected(co).PosInFieldY-top*fieldsize+topinfield-co.getImgPosY,
       co.image)
     else
       plocha.Canvas.Draw(co.PositionX*fieldsize-Left*fieldsize+leftinfield-co.getImgPosX,
       co.PositionY*fieldsize-top*fieldsize+topinfield-co.getImgPosY,
       co.image);
     end;
  
   begin
     // some more unimportant math
  
    vykresli(focus);                                                 
  
    For i:= Left+1 to left+2+(plocha.Width div fieldsize) do                                                         //vykreslení zdí
     For i1:= Top+1 to top+2+(plocha.Height div fieldsize) do
      if (i&lt; Walls.LevelSizeX) and (i1&lt; Walls.LevelSizeY) and (i&gt;=0) and (i1&gt;=0) and walls.IsZed(i,i1) then
       begin vykresli(walls^.GiveZed(i,i1)^);end;
  
    while abs((gettickcount() mod high(word))-lastframe) &lt; (1000 div FrameRateCap) do sleep(1); 
    lastframe:=gettickcount mod high (word);
  
    owner.Canvas.Draw(-fieldsize,-fieldsize,plocha);     
  
   end;
  </code></pre>
  
  <p>Can someone please tell me what am I doing wrong?</p>
  
  <p>Edit: I got the help I asked for, but after a few more years, I realized that the advice I really needed was not to use threads at all and try something like <a href="https://stackoverflow.com/questions/5399928/execute-action-every-x-seconds-delphi">this</a> instead.</p>