Frequent crash when running plugin multiple times



  • On 04/02/2016 at 04:25, xxxxxxxx wrote:

    Thank you, Yannick.
    I will prepare a listing of the snippets of relevant code, stripping out the junk and commenting as much as I can.



  • On 04/02/2016 at 04:48, xxxxxxxx wrote:

      
    """   
    Diffence Render   
    Written for Cinema 4D R15 and up   
    """   
      
    import c4d   
    from c4d import gui, plugins, utils, bitmaps, storage   
    from c4d.threading import C4DThread   
    from datetime import datetime   
    import time   
      
    import os   
      
    v_start_frame=2000   
    v_end_frame=2001   
    b_close=2010   
    b_calculate=2011   
    b_copy_rs=2012   
    quality=2020   
    the_filename=2030   
    b_filename=2040   
    b_abort=2050   
    t_info=2060   
    t_info2=2070   
      
    #be sure to use a unique ID obtained from www.plugincafe.com   
    PLUGIN_ID = 1036575   
      
    rImage1 = bitmaps.BaseBitmap()   
    rImage2 = bitmaps.BaseBitmap()   
    mImage = bitmaps.BaseBitmap()   
    start_frame=0   
    end_frame=99   
    current_frame=99   
    abort = False   
    calculating = False   
      
    document_time = c4d.BaseTime()   
    start_time = time.time()   
    last_estimate = 0   
    last_estimate_string = ""   
      
    frames_dir = ""   
    masks_dir = ""   
    main_dir = ""   
      
    average_change = 0   
      
    # *******************************************************************************   
      
    class RenderDisplay(gui.GeUserArea) :   
            
         highlight_line = c4d.Vector(0, 0.6, 0)   
         black = c4d.Vector(0)   
         white = c4d.Vector(1)   
         shadow_line = c4d.Vector(0.15)   
      
         success = False   
            
         def __init__(self,bmp) :   
              super(RenderDisplay, self).__init__()   
              self.bmp = rImage1   
            
         def DrawMsg(self, x1, y1, x2, y2, msg_ref) :   
      
              global start_frame   
              global end_frame   
              global current_frame   
              global abort   
              global calculating   
      
              #init draw region   
              self.OffScreenOn()   
              self.SetClippingRegion(x1, y1, x2, y2)   
                 
              the_color=self.GetColorRGB(c4d.COLOR_BG)   
              back_color=c4d.Vector(the_color['r']/255.0,the_color['g']/255.0,the_color['b']/255.0)   
              dimmed=c4d.Vector(c4d.utils.Clamp(0.0,1.0,back_color.x*1.1),c4d.utils.Clamp(0.0,1.0,back_color.y*1.1),c4d.utils.Clamp(0.0,1.0,back_color.z*1.1))   
      
              self.DrawSetPen(back_color)   
              self.DrawRectangle(x1, y1, x2, y2)   
                 
              self.DrawBorder(c4d.BORDER_THIN_IN,0,0,256,256)   
              self.DrawBorder(c4d.BORDER_THIN_IN,272,0,528,256)   
      
              if self.bmp:   
                   ww=self.bmp.GetBw()   
                   hh=self.bmp.GetBh()   
      
                   if ww>0 and hh>0:   
                        sc=254.0/float(ww)   
                        if hh*sc>254: sc=254.0/float(hh)   
      
                        nw=int(ww*sc)   
                        nh=int(hh*sc)   
                        nx=128-int(nw/2)   
                        ny=128-int(nh/2)   
      
                        self.DrawBitmap(self.bmp,nx,ny,nw,nh,0,0,ww,hh,c4d.BMP_NORMAL)   
      
                        if mImage:   
                             self.DrawBitmap(mImage,270+nx,ny,nw,nh,0,0,ww,hh,c4d.BMP_NORMAL)   
      
              # progress bar   
      
              self.DrawBorder(c4d.BORDER_THIN_IN,100,268,528,278)   
              self.DrawSetPen(self.white if calculating else dimmed)   
      
              percent=0.0   
              progress="Frame --/--"   
      
              if float(end_frame-start_frame)>0.0: percent=float(current_frame-start_frame+1)/float(end_frame-start_frame+1)   
      
              self.DrawRectangle(102, 270, int(102+424*percent), 276)   
            
              #self.DrawSetTextCol(self.white, back_color)   
              self.DrawSetTextCol(self.white if calculating else dimmed, back_color)   
              progress="Frame "+str(int(current_frame-start_frame+1))+"/"+str(int(end_frame-start_frame)+1)   
                 
              self.DrawText(progress if calculating else "Frame --/--", 2, 266)   
      
    # *******************************************************************************   
      
    class MyThread(c4d.threading.C4DThread) :   
      
         thumbnail = RenderDisplay(None)   
         v_quality=0   
      
         def Main(self) :   
      
              global start_frame   
              global end_frame   
              global current_frame   
              global abort   
              global calculating   
              global frames_dir   
              global masks_dir   
              global start_time   
              global main_dir   
              global average_change   
      
              # not calculating at the moment...   
              if calculating==False: return   
      
              # get the render data   
              doc=c4d.documents.GetActiveDocument()   
              rd=doc.GetActiveRenderData()   
      
              # bitmap size   
              o_ww=rd[c4d.RDATA_XRES]   
              o_hh=rd[c4d.RDATA_YRES]   
              ww=int(o_ww*self.v_quality)   
              hh=int(o_hh*self.v_quality)   
      
              # get the content of the render data container   
              new_rd=doc.GetActiveRenderData().GetData()   
      
              new_rd[c4d.RDATA_MULTIPASS_ENABLE] = False   
              new_rd[c4d.RDATA_PROJECTFILE] = False   
              new_rd[c4d.RDATA_FRAMESEQUENCE] = 1   
              new_rd[c4d.RDATA_SAVEIMAGE] = False   
              new_rd[c4d.RDATA_MULTIPASS_SAVEIMAGE] = False   
              new_rd[c4d.RDATA_XRES]=ww   
              new_rd[c4d.RDATA_YRES]=hh   
              new_rd[c4d.RDATA_ANTIALIASING] = 0 # no antialiasing   
      
              rImage1.Init(ww,hh,24)   
              rImage2.Init(ww,hh,24)   
              mImage.Init(ww,hh,24)   
      
              # perform the renders while not aborting and before the end of all frames   
              while current_frame<=end_frame and abort==False and calculating==True:   
      
                   new_rd[c4d.RDATA_FRAMEFROM]=c4d.BaseTime(current_frame,doc.GetFps())   
                   new_rd[c4d.RDATA_FRAMETO]=c4d.BaseTime(current_frame,doc.GetFps())   
                   doc.SetTime(c4d.BaseTime(current_frame,doc.GetFps()))   
      
                   res2=c4d.documents.RenderDocument(doc,new_rd,rImage1,c4d.RENDERFLAGS_EXTERNAL|c4d.RENDERFLAGS_NODOCUMENTCLONE)   
      
                   # prepare the mask   
                   if current_frame==start_frame:   
                        # first frame   
                        for yy in xrange(hh) :   
                             for xx in xrange(ww) :   
                                  mImage.SetPixel(xx,yy,255,255,255)   
                   else:   
                        for yy in xrange(hh) :   
                             for xx in xrange(ww) :   
                                  diff= 0 if rImage1.GetPixel(xx,yy)==rImage2.GetPixel(xx,yy) else 255   
                                  mImage.SetPixel(xx,yy,diff,diff,diff)   
                 
                   # save the frame and the mask   
                   frame_name=os.path.join(frames_dir,"frame_%05d.png" % (current_frame,))   
                   result=rImage1.Save(frame_name,c4d.FILTER_PNG)   
      
                   masks_name=os.path.join(masks_dir,"mask_%05d.png" % (current_frame,))   
                   result=mImage.Save(masks_name,c4d.FILTER_PNG)   
      
                   rImage1.CopyTo(rImage2)   
      
                   current_frame=current_frame+1   
      
              # RENDER FINISHED!!!   
      
              # create a report file   
              if os.path.exists(main_dir) :   
      
                   report_path=os.path.join(main_dir,"Report.txt")   
      
                   hf=open(report_path,'w')   
      
                   if hf:   
                        hf.write("Report for file < "+doc.GetDocumentName()+" >\n\n")   
      
                        hf.write("Date: "+time.strftime("%d/%m/%Y")+"\n\n")   
      
                        hf.write("Original frame size: %d x %d\n" % (o_ww,o_hh))   
                        hf.write("Final masks frame size: %d x %d\n\n" % (ww,hh))   
      
                        hf.write("Frame Range: frame %d to frame %d (%d in total)\n\n" % (start_frame,end_frame,end_frame-start_frame+1))   
      
                        if abort:   
                             hf.write("ABORTED BEFORE COMPLETION AT FRAME "+str(current_frame)+"!\n\n")   
      
                        spent=time.time()-start_time   
                        d=divmod(spent,86400)   
                        h=divmod(d[1],3600)   
                        m=divmod(h[1],60)   
                        s=m[1]   
      
                        hf.write("Total render calculation time: %02d:%02d:%02d\n\n" % (h[0],m[0],s))   
      
                        total_pixels=(end_frame-start_frame+1)*(ww*hh)   
                        aver=float(total_pixels-average_change)/float(total_pixels)   
      
                        hf.write("Average change: %d%% (less change is better)" % (100*(1.0-aver),))   
      
                        hf.close()   
      
              # clean the house   
              rImage1.FlushAll()   
              rImage2.FlushAll()   
              mImage.FlushAll()   
      
              abort=True   
              calculating=False   
      
    # *******************************************************************************   
      
    class DiffRender(gui.GeDialog) :   
            
         thumbnail = RenderDisplay(None)   
         thread = MyThread()   
      
         counter=0   
            
         def CreateLayout(self) :   
              self.SetTitle("Render Differences")   
                 
              self.GroupBegin(id=0, flags=c4d.BFH_SCALEFIT, title="", rows=1, cols=1, groupflags=c4d.BORDER_GROUP_IN)   
              self.GroupBorderSpace(5, 5, 5, 5)   
                 
              #give really unique ID to userarea, otherwise the update process will fail!   
              area = self.AddUserArea(id=1001, flags=c4d.BFH_SCALEFIT|c4d.BFV_TOP,initw=528, inith=204)   
              self.AttachUserArea(self.thumbnail, area)   
      
              self.AddStaticText(id=t_info2,flags=c4d.BFH_SCALEFIT|c4d.BFV_TOP,inith=0, name="Info: ---", borderstyle=c4d.BORDER_THIN_IN)   
      
              self.AddButton(id=b_abort, flags=c4d.BFH_CENTER,initw=64, inith=16, name="Abort")   
      
              self.AddSeparatorH(inith=0, flags=c4d.BFH_FIT)   
      
              # Filename   
              self.GroupBegin(id=0, flags=c4d.BFH_SCALEFIT|c4d.BFV_TOP, title="", rows=1, cols=3,)   
              self.AddStaticText(0,flags=c4d.BFH_LEFT|c4d.BFV_TOP,initw=90, inith=12, name="Masks Path")   
              self.AddEditText(id=the_filename,flags=c4d.BFH_SCALEFIT|c4d.BFV_TOP,initw=0, inith=12)   
              self.AddButton(id=b_filename, flags=c4d.BFH_FIT|c4d.BFV_TOP,initw=50, inith=12, name="...")   
              self.GroupEnd()   
      
              # quality   
              self.GroupBegin(id=0, flags=c4d.BFH_SCALEFIT|c4d.BFV_TOP, title="", rows=1, cols=3,)   
              self.AddStaticText(0,flags=c4d.BFH_FIT|c4d.BFV_TOP,initw=90, inith=12,name="Quality")   
              self.AddEditSlider(id=quality, flags=c4d.BFH_SCALEFIT|c4d.BFV_TOP,initw=50, inith=12)   
              self.AddStaticText(id=t_info,flags=c4d.BFH_FIT|c4d.BFV_TOP,initw=120, inith=12, name="--- x ---")   
              self.GroupEnd()   
      
              self.AddSeparatorH(inith=0, flags=c4d.BFH_FIT)   
      
              # frames   
              self.GroupBegin(id=0, flags=c4d.BFH_SCALEFIT|c4d.BFV_TOP, title="", rows=1, cols=6,)   
              self.AddStaticText(0,flags=c4d.BFH_FIT|c4d.BFV_TOP,initw=90, inith=12,name="From frame")   
              self.AddEditNumberArrows(id=v_start_frame, flags=c4d.BFH_FIT|c4d.BFV_TOP,initw=80, inith=12)   
              self.AddStaticText(0,flags=c4d.BFH_FIT|c4d.BFV_TOP,initw=74, inith=12,name="To frame")   
              self.AddEditNumberArrows(id=v_end_frame, flags=c4d.BFH_FIT|c4d.BFV_TOP,initw=80, inith=12)   
              self.AddButton(id=b_copy_rs, flags=c4d.BFH_SCALEFIT,initw=0, inith=12, name="Copy from Render Settings")   
              self.GroupEnd()   
      
              self.AddSeparatorH(inith=0, flags=c4d.BFH_FIT)   
                 
              self.GroupBegin(id=0, flags=c4d.BFH_RIGHT, title="", rows=1, cols=2,)   
              self.AddButton(id=b_close, flags=c4d.BFH_RIGHT,initw=60, inith=16, name="Close")   
              self.AddButton(id=b_calculate, flags=c4d.BFH_RIGHT,initw=80, inith=16, name="Calculate")   
              self.GroupEnd()   
              self.GroupEnd()   
              return True   
      
    # *******************************************************************************   
      
         def InitValues(self) :   
              self.SetInt32(id=quality,value=75,min=10,max=100)   
              self.SetInt32(id=v_start_frame,value=0)   
              self.SetInt32(id=v_end_frame,value=99)   
      
              doc=c4d.documents.GetActiveDocument()   
              rd=doc.GetActiveRenderData()   
              ww=rd[c4d.RDATA_XRES_VIRTUAL]   
              hh=rd[c4d.RDATA_YRES_VIRTUAL]   
              qual=float(self.GetInt32(quality))/100.0   
              self.SetString(id=t_info,value="( "+str(int(ww*qual))+" x "+str(int(hh*qual))+" )")   
      
              calculating=False   
      
              success=False   
      
              self.Enable(b_abort,False)   
      
              self.SetTimer(700)   
      
              return True   
      
    # *******************************************************************************   
      
         def Command(self,id,msg) :   
      
              global start_frame   
              global end_frame   
              global current_frame   
              global abort   
              global calculating   
              global document_time   
              global start_time   
              global last_estimate   
              global last_estimate_string   
              global frames_dir   
              global masks_dir   
              global main_dir   
              global average_change   
      
              doc=c4d.documents.GetActiveDocument()   
      
              if id==quality:   
                   rd=doc.GetActiveRenderData()   
                   ww=rd[c4d.RDATA_XRES_VIRTUAL]   
                   hh=rd[c4d.RDATA_YRES_VIRTUAL]   
                   qual=float(self.GetInt32(quality))/100.0   
                   self.SetString(id=t_info,value="( "+str(int(ww*qual))+" x "+str(int(hh*qual))+" )")   
      
              if id==b_close:   
                   self.Close()   
      
              if id==b_copy_rs:   
                   doc=c4d.documents.GetActiveDocument()   
                   rd=doc.GetActiveRenderData()   
                   start=rd[c4d.RDATA_FRAMEFROM].GetFrame(doc.GetFps())   
                   end=rd[c4d.RDATA_FRAMETO].GetFrame(doc.GetFps())   
                   self.SetInt32(id=v_start_frame,value=start)   
                   self.SetInt32(id=v_end_frame,value=end)   
      
              if id==b_filename:   
                   new_filename=c4d.storage.LoadDialog(title="Select the destination folder",flags=c4d.FILESELECT_DIRECTORY)   
                   if new_filename!=None:   
                        self.SetFilename(id=the_filename,fn=new_filename)   
      
              if id==b_calculate:   
                   # check the path   
                   new_filename=self.GetFilename(id=the_filename)   
                   if new_filename=="":   
                        c4d.gui.MessageDialog("A valid path needs to be set, in order to save the difference masks.")   
                        return True   
      
                   if not os.path.exists(new_filename) :   
                        c4d.gui.MessageDialog("A valid path needs to be set, in order to save the difference masks.")   
                        return True                       
      
                   main_dir=new_filename   
      
                   # check start and end frames   
                   start_frame=self.GetInt32(id=v_start_frame)   
                   end_frame=self.GetInt32(id=v_end_frame)   
                   if start_frame>=end_frame:   
                        c4d.gui.MessageDialog("There is a problem with the start and/or end frames.")   
                        return True   
      
                   # check if the required folders exist. If not, create them   
                   frames_dir=os.path.join(new_filename,"frames")   
                   if not os.path.exists(frames_dir) :   
                        os.mkdir(frames_dir)   
      
                   masks_dir=os.path.join(new_filename,"masks")   
                   if not os.path.exists(masks_dir) :   
                        os.mkdir(masks_dir)   
      
                   # clip the end_frame, if necessary   
                   max_frames=doc.GetMaxTime().GetFrame(doc.GetFps())   
                   if end_frame>max_frames:   
                        end_frame=max_frames   
      
                   # disable/enable GUI for calculations   
                   self.Enable(b_abort,True)   
                   self.Enable(b_calculate,False)   
                   self.Enable(b_close,False)   
                   self.Enable(b_filename,False)   
                   self.Enable(the_filename,False)   
                   self.Enable(quality,False)   
                   self.Enable(t_info,False)   
                   self.Enable(v_start_frame,False)   
                   self.Enable(v_end_frame,False)   
                   self.Enable(b_copy_rs,False)   
      
                   # adjust all the required variables   
                   abort=False   
                   calculating=True   
                   current_frame=start_frame   
                   start_time=time.time()   
                   last_estimate=time.strptime("23:59:59","%H:%M:%S")   
                   last_estimate_string=""   
                   average_change=0   
                   self.counter=1   
                   document_time=doc.GetTime()   
                   self.thread.v_quality=float(self.GetInt32(quality))/100.0   
      
                   # start the calculation   
                   self.thread.Start()   
      
      
              if id==b_abort:   
                   abort=True   
      
                   self.SetString(id=t_info2,value="Aborting...")   
                      
                   self.Enable(b_abort,False)   
                   self.Enable(b_calculate,True)   
                   self.Enable(b_close,True)   
                   self.Enable(b_filename,True)   
                   self.Enable(the_filename,True)   
                   self.Enable(quality,True)   
                   self.Enable(t_info,True)   
                   self.Enable(v_start_frame,True)   
                   self.Enable(v_end_frame,True)   
                   self.Enable(b_copy_rs,True)   
      
                   doc.SetTime(document_time)   
      
              #c4d.EventAdd()   
              return True   
      
    # *******************************************************************************   
      
         def Timer(self, msg) :   
      
              global start_frame   
              global end_frame   
              global current_frame   
              global abort   
              global calculating   
              global document_time   
              global start_time   
              global last_estimate   
              global last_estimate_string   
      
              if self.counter==0:   
                   if calculating and not abort:   
                        spent=time.time()-start_time   
                        d=divmod(spent,86400)   
                        h=divmod(d[1],3600)   
                        m=divmod(h[1],60)   
                        s=m[1]   
      
                        time_string="Elapsed: %02d:%02d:%02d" % (h[0],m[0],s)   
      
                        if current_frame>start_frame:   
                             each_frame=spent/float(current_frame-start_frame-.1)   
                             estimated=(end_frame-current_frame)*each_frame   
                                
                             d=divmod(estimated,86400)   
                             h=divmod(d[1],3600)   
                             m=divmod(h[1],60)   
                             s=m[1]   
                             last_estimate_string=" ( Estimated time to finish: %02d:%02d:%02d )" % (h[0],m[0],s)   
                             last_estimate=estimated   
      
                        time_string=time_string+last_estimate_string   
                        self.SetString(id=t_info2,value=time_string)   
      
              self.counter=(self.counter+1) % 3   
      
              if abort==True:   
                   self.thread.End(True)   
                   calculating=False   
                   self.Enable(b_abort,False)   
                   self.Enable(b_calculate,True)   
                   self.Enable(b_close,True)   
                   self.Enable(b_filename,True)   
                   self.Enable(the_filename,True)   
                   self.Enable(quality,True)   
                   self.Enable(t_info,True)   
                   self.Enable(v_start_frame,True)   
                   self.Enable(v_end_frame,True)   
                   self.Enable(b_copy_rs,True)   
                   doc=c4d.documents.GetActiveDocument()   
                   doc.SetTime(document_time)   
                   c4d.StopAllThreads()   
                           
              #Since we can't update the USER_AREA manually while rendering   
              #We must ReDraw it constantly before we start rendering   
              #Only do this ReDrawing when we are actually rendering!!!   
              if self.thread.IsRunning() :   
                   self.thumbnail.Redraw()   
                      
      
    # *******************************************************************************   
      
    class BitmapManagerCommandData(c4d.plugins.CommandData) :   
         dialog = None   
      
         def Execute(self, doc) :   
              """Just create the dialog when the user clicked on the entry   
              in the plugins menu to open it."""   
              if self.dialog is None:   
                 self.dialog = DiffRender()   
      
              return self.dialog.Open(dlgtype=c4d.DLG_TYPE_MODAL, pluginid=PLUGIN_ID, defaulth=300, defaultw=550)   
      
         def RestoreLayout(self, sec_ref) :   
              """Same for this method. Just allocate it when the dialog   
              is needed"""   
              if self.dialog is None:   
                 self.dialog = DiffRender()   
      
              return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref)   
      
    # *******************************************************************************   
      
    if __name__ == "__main__":   
          bmp = bitmaps.BaseBitmap()   
          dir, f = os.path.split(__file__)   
          fn = os.path.join(dir, "res", "icon.tif")   
          bmp.InitWith(fn)   
          c4d.plugins.RegisterCommandPlugin(id=PLUGIN_ID, str="Differences Render",   
                                                  help="Renders set of bitmaps with differences between animation frames.",info=0,   
                                                      dat=BitmapManagerCommandData(), icon=bmp)   
    


  • On 04/02/2016 at 08:48, xxxxxxxx wrote:

    Hi Rui,

    That's quite a long piece of code 🙂.

    First, you're doing forbidden operations in the custom thread:
    - Modification of the active document (doc.SetTime())
    - File operation (open(), write() etc.)

    RenderDocument() is called without passing the thread... So it doesn't know it runs from a custom thread.
    The last (optional) parameter th should be passed self.Get()).

    The Main() function of your thread should be used to call RenderDocument() mainly. Modifying the rendered bitmap there should be fine too.
    All other operations have to be done from the dialog. Modify the document there and run the thread for each frame to render.
    Then do also the file operation in your dialog after the render and thread have finished each frame.

    Also I'm not sure the behavior between globals and a C4DThread is safe. You'd better use members of the custom threads.
    When the render operation has to be aborted you shouldn't rely on a global bool but immediately end the thread.



  • On 04/02/2016 at 09:21, xxxxxxxx wrote:

    Thank you for the pointers. I will change my code, then.
    Just one thing... how can I know that a render operation finished for each frame, in order to advance with the bitmap operations?



  • On 04/02/2016 at 09:24, xxxxxxxx wrote:

    Oh, another thing.
    If I don't set the time of the document inside the thread with doc.SetTime(), simply setting the start/end frame of the render with

    new_rd[c4d.RDATA_FRAMEFROM]=c4d.BaseTime(current_frame,doc.GetFps())
    new_rd[c4d.RDATA_FRAMETO]=c4d.BaseTime(current_frame,doc.GetFps())

    will be enough? I mean, will it calculate the animation correctly? Even files with particles and dynamics?



  • On 05/02/2016 at 01:23, xxxxxxxx wrote:

    Hi Rui,

    Originally posted by xxxxxxxx

    How can I know that a render operation finished for each frame, in order to advance with the bitmap operations?

    Use your dialog's Timer() function to keep track of the running thread. When finished do the bitmap and file operations.
    Then start another thread for the next render if cycle hasn't finished.

    Originally posted by xxxxxxxx

    If I don't set the time of the document inside the thread with doc.SetTime(), simply setting the start/end frame of the render with

    new_rd[c4d.RDATA_FRAMEFROM]=c4d.BaseTime(current_frame,doc.GetFps()) 
    new_rd[c4d.RDATA_FRAMETO]=c4d.BaseTime(current_frame,doc.GetFps())

    will be enough? I mean, will it calculate the animation correctly? Even files with particles and dynamics?

    To make sure the document to render is updated for a given frame call ExecutePasses() after SetTime().



  • On 05/02/2016 at 07:07, xxxxxxxx wrote:

    Thank you, Yannick.
    That sounds logical.
    My only problem is that my cycle is now in the main thread and it happens in the Command method, while the cycle is running, I have no events for the clicking on the Abort button.
    How can I create a cycle, when the user clicks "Calculate" and still have a way to cancel the render, by clicking "Abort"?



  • On 08/02/2016 at 03:47, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    My only problem is that my cycle is now in the main thread and it happens in the Command method, while the cycle is running, I have no events for the clicking on the Abort button.
    How can I create a cycle, when the user clicks "Calculate" and still have a way to cancel the render, by clicking "Abort"?

    What do you mean by 'cycle'?
    You shouldn't use a while loop for the render cycle. Use Timer() to check if the thread for the render has finished. If yes do your bitmap and file operations then starts the next render thread.



  • On 08/02/2016 at 13:22, xxxxxxxx wrote:

    Oh, ok. Requires a little more "thinking of" but I will give it a try
    Another thing... instead of using global variables should I make them all childs of the user thread process?
    Thank you, Yannick.



  • On 09/02/2016 at 00:15, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    Another thing... instead of using global variables should I make them all childs of the user thread process?

    It's always better to use member variable in classes. This forces to write cleaner and safer code.
    Avoid as much as possible using global variables.


Log in to reply