Stopping a cycle of renders



  • On 25/01/2016 at 05:49, xxxxxxxx wrote:

    Ok, solved the hanging problem by ending the thread with self.thread.End(False) instead of just self.thread.End()

    Now, Still haven't solved the processing of the bitmaps after each render.



  • On 25/01/2016 at 07:28, xxxxxxxx wrote:

    Actually, it is not really solved
    If I abort and press the render button again, it hangs.
    Damn!!!



  • On 25/01/2016 at 08:34, xxxxxxxx wrote:

    Something to keep in mind.

    I know very little about threads. I never use them.
    When I was playing around with this yesterday. I tried using the python threading instead of the C4D threading. And I looked around the internet about how to stop threads. And I was surprised to learn that there is no such thing as stopping a thread. Stopping a thread apparently is a very, very bad idea.
    There are hacks to do it. But it's generally a bad idea.

    In the C4D thread class. We have the thread.end(True/False) method to stop them.
    Setting the param to True (or keeping it empty) will try to stop the thread immediately.
    Setting the param to False will try to stop the thread. But it won't stop until what it's working on has finished.
    But based on my research. I would say that Maxon knows that "stopping" a thread is a very bad idea. So I'm guessing that their end() method does it softly and safely. And not abruptly.

    So it sounds to me that you are trying to work on the image before the RenderDocument() method has finished running.
    I think you need to worry more about if the RenderDocument() method has finished before attempting to do something with the images. Rather than if the thread has stopped.

    Keep at it. I think you'll get it working eventually.

    -ScottA



  • On 25/01/2016 at 09:31, xxxxxxxx wrote:

    I'm stubborn ;-)
    I'm still trying and I will get there, eventually :-)
    Do you know how can I check if the RenderDocument finished?



  • On 25/01/2016 at 10:17, xxxxxxxx wrote:

    Nope.
    I spent a little bit of time yesterday trying to find a python method that checks if a file is being written to or not as a way to check if the RenderDocument() was writing to a file. And I didn't find anything worth while.
    I mostly saw people posted things like checking the time files were written as a way to tell if they were being written to or not.

    I'm sure there's a better way. I only spent about 15mins. looking around.
    I was too caught up in watching the football games.🙂

    -ScottA

    *Edit-  I don't know if you can rely on the return from RenderDocument() in cases where you're rendering multiple frames. Or calling it many times in a thread. It does have a return that can be checked. But I don't know if it can be used in your situation or not.

       res = documents.RenderDocument(doc, rd, bmp, c4d.RENDERFLAGS_EXTERNAL)  
      if res == c4d.RENDERRESULT_OK: print" We've finished"
    


  • On 25/01/2016 at 10:50, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    In the C4D thread class. We have the thread.end(True/False) method to stop them.
    Setting the param to True (or keeping it empty) will try to stop the thread immediately.
    Setting the param to False will try to stop the thread. But it won't stop until what it's working on has finished.
    But based on my research. I would say that Maxon knows that "stopping" a thread is a very bad idea. So I'm guessing that their end() method does it softly and safely. And not abruptly.

    Not quite. The End() method does the same in "stopping" the thread independent from whether you
    pass True or False to it. All it does is set a flag in the thread object that will cause TestBreak() to return
    false. The RenderDocument() function will call that method to check if it should continue to process or
    not. There's no real "stopping" happening in terms of what you might think of relating to processor 
    (where you can just kill a process with the Task Manager [Win] or Activity Monitor [Mac]).

    This is in fact the way you "stop" a thread: By telling it to stop. Note that the example below should
    just outline  the way these two components are implemented. You can not  pass a Python Thread to
    the RenderDocument function, it must be a C4DThread.

    from threading import Thread
      
    def MyRenderDocument(doc, bmp, thread) :
      ''' Sample implementation of c4d.documents.RenderDocument(). '''
      
      while not thread.TestBreak() :
        # continue to render ...
      
    class MyC4DThread(Thread) :
      ''' Sample implementation of C4DThread.End(). '''
      
      def __init__(self) :  
        super(MyC4DThread, self).__init__()
        self.stopped = threading.Event()
      
      def End(self, wait) :
        self.stopped.set()
        if wait:
          self.join()
      
      def TestBreak(self) :
        return self.stopped.is_set()
      
      def run(self) :
        MyRenderDocument(doc, self)
    


  • On 25/01/2016 at 10:54, xxxxxxxx wrote:

    @Rui If you want to render multiple frames, I think you should call RenderDocument() for each frame.
    Afaik there is no way to receive some sort of callback when a frame finished. You know that RenderDocument()
    finished when the function returned (ie. all code that you place after the RenderDocument() code is
    executed after it finished).

    @Scott Afaik RenderDocument() does not do the "Save" part for you, so you would have to save it
    by yourself after the rendering.

    TL;DR if you're still having problems with C4D hanging, you have to make sure RenderDocument()
    finishes. You should use the C4DThread.TestBreak() interaction with RenderDocument() to stop the
    function (and with it the thread) rather than the way Scott did it in his example using
    RENDERFLAGS_EXTERNAL +  CallCommand() to stop the rendering.



  • On 25/01/2016 at 11:22, xxxxxxxx wrote:

    The script Niklas posted does seem to stop the rendering Rui. Although I never tested it by trying to do anything with the resulting image.

    I would not use my example at all. It was just a wild guess on my part.

    -ScottA



  • On 25/01/2016 at 14:05, xxxxxxxx wrote:

    I will have to save the bitmap myself, I know that :-)
    And, to make sure the render finishes, for each frame, my abort button will only set a variable to True and that variable will be tested after the RenderDocument.
    So, the render will stop after the frame has finished render, if the user pressed the Abort button, in the meanwhile.
    Well, at least that is what I'm going to try to do :-)



  • On 25/01/2016 at 15:30, xxxxxxxx wrote:

    And you're sure you don't want the user to be able to stop the render process mid-render, eg. if the
    frame would still take 5 hours to render?



  • On 26/01/2016 at 01:59, xxxxxxxx wrote:

    The renders are always much smaller than a full render (they are almost thumbnails) and with antialias off.
    So, they don't take up much time rendering.
    Also, this is for a plugin that will be useful for animations, not for stills. I don't think that animators will create animations that take up five hours per frame (although... possible ;-) )



  • On 27/01/2016 at 03:24, xxxxxxxx wrote:

    If you say so. I just don't understand what the problem is in doing it the "right way". I'd get furious
    if the plugin lets me wait 4 seconds after pressing stop. Since the possibility to stop the rendering right
    away is given and its easy to implement, why not do it.



  • On 27/01/2016 at 04:23, xxxxxxxx wrote:

    Well, I would prefer to do it the right way.
    But I'm still not able to do it
    This is much harder than I expected.



  • On 27/01/2016 at 04:42, xxxxxxxx wrote:

    In the...

    def MyRenderDocument(doc, bmp, thread) :
    ''' Sample implementation of c4d.documents.RenderDocument(). '''

    while not thread.TestBreak() :
        # continue to render ...

    The # continue to render is just a call to the RenderDocument?
    Will this stop the render in mid render? Will it not leave things hanging and requiring house cleaning?



  • On 27/01/2016 at 04:57, xxxxxxxx wrote:

    This is my main user thread, used for rendering:

    Class MyThread(c4d.threading.C4DThread) :

    thumbnail = RenderDisplay(None) # the user area
         v_quality=0

    def Main(self) :

    doc=c4d.documents.GetActiveDocument()
              rd=doc.GetActiveRenderData()

    max_frames=doc.GetMaxTime().GetFrame(doc.GetFps())
              if self.thumbnail.end_frame>max_frames:
                   self.thumbnail.end_frame=max_frames

    # bitmap size
              ww=int(rd[c4d.RDATA_XRES]*self.v_quality)
              hh=int(rd[c4d.RDATA_YRES]*self.v_quality)

    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

    rImage.Init(ww,hh,24)

    while self.thumbnail.current_frame<=self.thumbnail.end_frame:

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

    if self.thumbnail.abort==False:
                        res=c4d.documents.RenderDocument(doc,new_rd,rImage,c4d.RENDERFLAGS_EXTERNAL)
                        #res=c4d.documents.RenderDocument(doc,new_rd,rImage,c4d.RENDERFLAGS_NODOCUMENTCLONE|c4d.RENDERFLAGS_EXTERNAL,None)
                        self.thumbnail.current_frame=self.thumbnail.current_frame+1
                   else:
                        self.calculating=False

    And it is not working


Log in to reply