Forum Discussion

chaklasiyanikun's avatar
4 years ago
Solved

Faced "Execution timeout (runtime error &h23)" Error in Function Calculation

I make one sample App for Roku. It is as below.

MainScene.brs

sub init()
    m.TaskNodeThread = CreateObject("roSGNode", "TaskNodeThread")
    m.TaskNodeThread.control = "RUN"
end sub

MainScene.xml

<?xml version="1.0" encoding="UTF-8"?>
<component name="MainScene" extends="Scene" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://devtools.web.roku.com/schema/RokuSceneGraph.xsd">
     <script type="text/brightscript" uri="pkg:/components/MainScene.brs" />
</component>

TaskNodeThread.brs

sub init()
     m.TestContent = testContentFunction(testData)
end sub

function testContentFunction(testData as String) as String

'Here I need some calculation and It takes a lot of time.
'It takes around 50 to 60 Sec and I got this error in this function.
'I know Rendered thread timeout limit is 10 Sec that's why I have written this
function in Task Node.

'Even so, it waits only for 10 Sec.
'Can anyone suggest where should I write this type of logic in Roku which is not
affected by UI.


end function

TaskNodeThread.xml

<?xml version="1.0" encoding="UTF-8"?>
<component name="TaskNodeThread" extends="Task" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://devtools.web.roku.com/schema/RokuSceneGraph.xsd">
     <script type="text/brightscript" uri="pkg:/components/TaskNodeThread.brs" />
</component>
  • Review the documentation on correctly setting up a task

    https://developer.roku.com/docs/references/scenegraph/control-nodes/task.md

    the way you have set this up 'testContentFunction(testData)' will run when created

    MainScene.brs set testdata for task here before "run"

    sub init()
        m.TaskNodeThread = CreateObject("roSGNode", "TaskNodeThread")
    m.TaskNodeThread.TestContent=testData
    m.TaskNodeThread.observefield("resultContent","onResultContentChanged") 'observe field to see if we are done with task
    m.TaskNodeThread.control = "RUN"
    end sub

    sub onResultContentChanged(event) 'called when task completes
    data=event.getdata()
    'do stuff with data here
    end sub

    TaskNodeThread.xml needs and interface for test content

    <?xml version="1.0" encoding="UTF-8"?>
    <component name="TaskNodeThread" extends="Task" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://devtools.web.roku.com/schema/RokuSceneGraph.xsd">
    <interface>
    <field id = "resultcontent" type = "node" /> <field id = "testcontent" type = "node" /> </interface>
    <script type="text/brightscript" uri="pkg:/components/TaskNodeThread.brs" /> </component>

    TaskNodeThread.brs m.top.functionName is what is called when .control="run" is set

    sub init()
    m.top.functionName = "testContentFunction" end sub

    function testContentFunction() as String
    testdata=m.top.testcontent
    'do stuff here
    m.top.resultContent = resultOfStuffDone 'signal task has completed
    end function

     

4 Replies

  • Review the documentation on correctly setting up a task

    https://developer.roku.com/docs/references/scenegraph/control-nodes/task.md

    the way you have set this up 'testContentFunction(testData)' will run when created

    MainScene.brs set testdata for task here before "run"

    sub init()
        m.TaskNodeThread = CreateObject("roSGNode", "TaskNodeThread")
    m.TaskNodeThread.TestContent=testData
    m.TaskNodeThread.observefield("resultContent","onResultContentChanged") 'observe field to see if we are done with task
    m.TaskNodeThread.control = "RUN"
    end sub

    sub onResultContentChanged(event) 'called when task completes
    data=event.getdata()
    'do stuff with data here
    end sub

    TaskNodeThread.xml needs and interface for test content

    <?xml version="1.0" encoding="UTF-8"?>
    <component name="TaskNodeThread" extends="Task" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://devtools.web.roku.com/schema/RokuSceneGraph.xsd">
    <interface>
    <field id = "resultcontent" type = "node" /> <field id = "testcontent" type = "node" /> </interface>
    <script type="text/brightscript" uri="pkg:/components/TaskNodeThread.brs" /> </component>

    TaskNodeThread.brs m.top.functionName is what is called when .control="run" is set

    sub init()
    m.top.functionName = "testContentFunction" end sub

    function testContentFunction() as String
    testdata=m.top.testcontent
    'do stuff here
    m.top.resultContent = resultOfStuffDone 'signal task has completed
    end function

     

    • chaklasiyanikun's avatar
      chaklasiyanikun
      Roku Guru

      Thank you so much for your response. That's what I was looking for.
      I read this documentation for stopping the Task node. Is there any way or field available for the Stopping the Task Thread between the Logic?

      like

      m.TaskNodeThread.control = "STOP"

      And

      I take the type array in the field and use it like below. But it gives this error => Interface is not a member of BrightScript Component (runtime error &hf3). Is it the correct way I used it?

      TaskNodeThread.xml

      <field id = "resultcontent" type = "node" />

      TaskNodeThread.brs

      function testContentFunction() as String
      
           testdata=m.top.testcontent
           'do stuff here
      
            for val = 0 to Value - 1
                m.top.resultContent.Push(Value[val])
            end for
      
         return ""
      
      end function

      The single value, I am able to fetch using event. But, I need to fill this whole value in an array.
      Using Global value I am able to do
      But, only assocaaray available in Global Node.

       

      So, I need to convert array to assocarray in Task Thread and Render thread I again convert to assocarray to array and used. This is right approch or you suggest me to any better approch?

      The single value, I am able to fetch using event. But, I need to fill this whole value in an array.

      Using Global value I am able to do

      But, only assocaaray available in Global Node. So I convert to array to assocarray in Task Thread and Render thread I again convert to assocarray to array and used. This is right approch or you suggest me to any better approch.

       

       m.global.addfield("resultContentResponse","assocarray", TRUE)

       

      TaskNodeThread

      contentArr = CreateObject("roArray",Value.Count(),false)
      for val = 0 to Value - 1 
      contentArr.Push(Value[val])
      end for assocArrayContent = formatJSON(contentArr) m.Global.resultContentResponse = assocArrayContent

       

      MainScene

      response = ParseJson(m.Global.resultContentResponse)
      'do stuff here 
      For Each res In response
      Print "My Response here: " + res
      End For

       

      • necrotek's avatar
        necrotek
        Roku Guru

        Sure... you should be able to m.TaskNodeThread.control = "STOP" at some point in your mainscene after the task has been started.

        if you need to return an array change the type to array. same with test content if you want to pass as a different type such as "string".

        <field id = "resultcontent" type = "array" />
        <field id = "testcontent" type = "string" />

        if you do this like below, then it will trigger the onResultContentChanged() in the mainscene each time you push to the array since this is what is being observed.

             for val = 0 to Value - 1
                  m.top.resultContent.Push(Value[val])
              end for

         Do something like this instead

              resultContent=[]
        for val = 0 to Value.count() - 1 resultContent.Push(Value[val]) end for
        m.top.resultContent.append(resultContent) 'only trigger once you are done

        I don't think you want to store this in the GlobalAA node to pass the data

        from mainscene you can access the result 

        response = m.TaskNodeThread.resultContent