简体   繁体   中英

Roku Brightscript, Render Thread to Task Thread transfer

How can we pass Associative Array or SGNode to task thread from render thread without losing the values? In the following example, I am adding the request in a queue in the render thread but when in the go function, which is in the task thread, I try to access the request queue then it gives me an empty queue. How to Solve the issue?

sub init()
  print "UriHandler.brs - [init]"
  m.Port = createObject("roMessagePort")
  m.top.numBadRequests = 0
  m.requestQueue = createObject("roArray", 10, true)
  m.processing = false
  m.top.functionName = "go"
  m.top.control = "RUN"
  m.top.observeField("request", "addToQueue")
end sub

function addToQueue(data)
  m.requestQueue.push(data.getData())
end function 


'Task function
sub go()
  print "UriHandler.brs - [go]"
  ' Holds requests by id
  m.jobsById = {}
  ' UriFetcher event loop
  while true
    msg = wait(0, m.port)
    mt = type(msg)
    print "--------------------------------------------------------------------------"
    print "Received event type '"; mt; "'"
    ' If a request was made
    if mt = "roSGNodeEvent"
      if msg.getField()="request"
        print "got a request"
        if m.requestQueue.count()>0
          ProcessRequest(m.requestQueue.shift())
        end if
      else
        print "Error: unrecognized field '"; msg.getField() ; "'"
      end if
    ' If a response was received
    else if mt="roUrlEvent"
      processResponse(msg)
    ' Handle unexpected cases
    else
     print "Error: unrecognized event type '"; mt ; "'"
    end if
  end while
end sub

' function ProcessNextRequest()
'   request = m.requestQueue.shift()
'   ProcessRequest(request)
'   print "setting processing false"
' end function

function ProcessRequest(request as Object) as Boolean
  print "HTTPHandler - [addRequest]"
  if type(request) = "roAssociativeArray"
    print request
    context = request.context
      if type(context) = "roSGNode"
      parameters = context.parameters
      if type(parameters)="roAssociativeArray"
        headers = parameters.headers
        method = parameters.method
        uri = parameters.uri
        bodyString = ""
        if method = "POST" or method = "PUT"
          body = parameters.body
          bodyString = body.toStr()
        end if
        if type(uri) = "roString"
          urlXfer = createObject("roUrlTransfer")
          urlXfer.SetCertificatesFile("common:/certs/ca-bundle.crt")
          urlXfer.InitClientCertificates()
          urlXfer.setPort(m.Port)
          urlXfer.setUrl(uri)
         ' Add headers to the request
          for each header in headers
            urlXfer.AddHeader(header, headers.lookup(header))
          end for
          print "headers are " headers
          'should transfer more stuff from parameters to urlXfer
          idKey = stri(urlXfer.getIdentity()).trim()
          'Make request based on request method
          'AsyncGetToString returns false if the request couldn't be issued
          if method = "POST" or method = "PUT" or method = "DELETE"
            urlXfer.setRequest(method)
            ok = urlXfer.AsyncPostFromString(bodyString)
          else
            ok = urlXfer.AsyncGetToString()
          end if
          if ok then
            m.jobsById[idKey] = {
              context: request
              xfer: urlXfer
            }
          else 
            print "send not successful"
          end if
          print "Initiating transfer '"; idkey; "' for URI '"; uri; "'"; " succeeded: "; ok
        else
          print "Error: invalid uri: "; uri
          m.top.numBadRequests++
        end if
      else
        print "Error: parameters is the wrong type: " + type(parameters)
        return false
      end if
      else
      print "Error: context is the wrong type: " + type(context)
          return false
      end if
  else
    print "Error: request is the wrong type: " + type(request)
    return false
  end if
  print "--------------------------------------------------------------------------"
  return true
end function

'Received a response
sub processResponse(msg as Object)
  idKey = stri(msg.GetSourceIdentity()).trim()
  job = m.jobsById[idKey]
  if job <> invalid
    context = job.context
    parameters = context.context.parameters
    uri = parameters.uri
    print "Response for transfer '"; idkey; "' for URI '"; uri; "'"
    result = {
      code:    msg.GetResponseCode(),
      headers: msg.GetResponseHeaders(),
      content: msg.GetString(),
    }
    print result
    print "response headers"
    print result.headers
    job.context.context.response = result
    m.jobsById.delete(idKey)
  else
    print "Error: event for unknown job "; idkey
  end if
  ' ProcessNextRequest()
  print "--------------------------------------------------------------------------"
end sub`

You can create a custom task component which extends the Task node, with the additional interface fields you need.

<?xml version="1.0" encoding="UTF-8"?>

<component name="CustomTask" extends="Task">
    <interface>
        <field id="aaField" type="assocarray"/>
        <field id="nodeField" type="node" />
    </interface>
</component>
sub init()
    m.top.functionName = "getContent"
end sub

sub getContent()
    ? m.top.aaField ' Prints the associative array passed
    ? m.top.nodeField ' Prints the SG node passed
end sub

You can then create an instance of the newly created task node and pass the data you want to its fields.

contentNode = createObject("roSGNode", "ContentNode")
m.someTask = createObject("roSGNode", "CustomTask")
m.someTask.aaField = { hello: "world" }
m.someTask.nodeField = contentNode
m.someTask.control = "run"

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