I can’t find much information/ any examples of multithreading. Am I missing something in the templates or documentation. The developer guide say that it is possible so I would have to think there are examples somewhere. I get that you are supposed to use message ports but how do you “fire off” a new thread?
Whether a BrightScript Component launches a background thread to perform asynchronous operations is a decision made by the Object implementer. Often an object will have synchronous and asynchronous versions of the same method.
That to me sounds like I can create a background thread for some tasks. But that is really the only reference, perhaps it is just a typo. So then the question becomes how do I using asynchronous operations without another thread?
Ok, thanks. That sentence probably needs to be clarified. It’s referring to the underlying C code that implements the Brightscript objects, not to creating threads in Brightscript code.
Certain operations, like HTTP requests using roUrlTransfer, can be done with asynchronous operations. The only way to achieve something like that in your own code is to break up the code into smaller pieces that can be called from your event loop, perhaps based on a timer.
Ok so how would I say handle button clicks while rendering an image? They could never happen at the same time? I would have to handle the rendering then the click? If rendering gets hosed (for whatever reason) doesn’t that mean I lose the ability to handle key presses?
By “rendering an image”, do you just mean doing a DrawObject or something like that? That operation is pretty fast (much less than a frame interval) and cannot get “hosed”. Could you explain in more detail the scenario you’re concerned about?
Theoretically, If you really need to you can download your graphics
Asynchronously using asyncgettofile. This writes it
To the temp directory. You then load them
From there which is very quick. If you need to check
For keypress just use the same port as your
Window. Checking for both types of events to come in
“NewManLiving” wrote:
Theoretically, If you really need to you can download your graphics
Asynchronously using asyncgettofile. This writes it
To the temp directory. You then load them
From there which is very quick. If you need to check
For keypress just use the same port as your
Window. Checking for both types of events to come in
Or use the roTextureManager, which can download and load the bitmap asynchronously.
I am implementing Lazy Loading of images in a carousel made on roScreen. There are around 100 images which I am fetching from the web. I am using roTextureEvent to get the images asynchronously and drawing the objects on the screen. In this approach, when the requests for the images are fired, I am not able to handle the button events as the request send process seems to be slow. I want an roGridScreen type experience where images can be loaded even if the scrolling is happening.
I have tried to make my code into as small bits as I could. But the experience remains the same.
Could you please guide me if there is a way?
“sanyam” wrote:
I am implementing Lazy Loading of images in a carousel made on roScreen. There are around 100 images which I am fetching from the web. I am using roTextureEvent to get the images asynchronously and drawing the objects on the screen. In this approach, when the requests for the images are fired, I am not able to handle the button events as the request send process seems to be slow. I want an roGridScreen type experience where images can be loaded even if the scrolling is happening.
I have tried to make my code into as small bits as I could. But the experience remains the same.
Could you please guide me if there is a way?
We’d need to see your code. There may be a slight delay when you issue the request (<10ms), but nothing that should prevent you from handling button events.
Are you firing all your requests at once and not sending and polling each one as it comes in? It performs best when you let it fly - blast your requests all at once if you only have a hundred at standard poster sizes, and if you must page, page at the largest amount you can based upon performance, and don’t send/poll for each request. What works well for me is to create a queue or table using an associativearray, load them on and pop them off as a service. No matter how you do it the request object must survive from send to receive, so you have to include it in your table or assign it to a structure member that goes into the table. I use structures or small classes that define what is to be done with the information. But below is
some pseudo code that gives the general idea. And lastly if you are drawing right when you receive them, then you need to make sure that everything that is time
consuming is done outside, or you will block. Font creation is very time consuming and drawtext can be if you use a lot of it
'
for i = 0 to myUrlCount - 1
TRequest = CreateObject( "roTextureRequest", someUrl[ i ] )
TextureID = TRequest.GetID().ToStr()
myList.AddReplace( TextureID, { Request: TRequest, ServiceA: a_ItemA, ServiceB: a_ItemB } )
myTManager.RequestTexture( TRequest )
end for
In your event handler just look up the code
' Process the message to get your bitmap, check for errors etc
' Then locate it in the table and pass it along or draw it
l_ID = msg.GetID().ToStr()
l_request = myList.LookUpCI( l_ID )
l_request.ServiceA.DoSomethingWith( theBitmap )
' Delete the key
myList.Delete( l_ID )
Just one additional thing. under ideal conditions if you are requesting a large
Number they arrive very rapidly. One hundred poster size bitmaps in my
Environment arrives in about 2.5 ( best case senario) seconds. So if i were to attempt to
Draw all these as they came then I would expect to see some sluggishness
So the method I described is best for caching. My Drawing is more conservative
“sanyam” wrote:
I am implementing Lazy Loading of images in a carousel made on roScreen. There are around 100 images which I am fetching from the web. I am using roTextureEvent to get the images asynchronously and drawing the objects on the screen. In this approach, when the requests for the images are fired, I am not able to handle the button events as the request send process seems to be slow.
Assuming you haven’t accidentally turned off the Async behavior with ifTextureRequest.SetAsync(false) I would recommend you use a separate port for your texture requests than for your screen and button events, In my experience it seems as if button events are either getting dropped or just buried under other events coming from the texture manager, and so the program can be unresponsive.
“RokuJoel” wrote:
… I would recommend you use a separate port for your texture requests than for your screen and button events, In my experience it seems as if button events are either getting dropped or just buried under other events coming from the texture manager, and so the program can be unresponsive.
That’s quite interesting - intuitively there should be no difference, since a “port” should only be a vessel for events that occur anyway. There might be implementation limitation though - say something like limited length of event queue (or extreme case: event queue has length 1, only one event can be pending - like ye olde Apple2 keyboard buffer). Do let us know RokuJoel, if you eke out info on that from the source.
“RokuJoel” wrote:
… I would recommend you use a separate port for your texture requests than for your screen and button events, In my experience it seems as if button events are either getting dropped or just buried under other events coming from the texture manager, and so the program can be unresponsive.
That’s quite interesting - intuitively there should be no difference, since a “port” should only be a vessel for events that occur anyway. There might be implementation limitation though - say something like limited length of event queue (or extreme case: event queue has length 1, only one event can be pending - like ye olde Apple2 keyboard buffer). Do let us know RokuJoel, if you eke out info on that from the source.
The port is FIFO, so if you have one port, issuing a large number of texture requests can delay processing of other events. If you use two different ports, then your event loop can look something like this, so the large number of texture request events don’t delay other processing…
While True
msg = screenPort.GetMessage()
If msg <> invalid Then
' handle key press
End If
msg = texturePort.GetMessage()
If msg <> invalid Then
' handle texture request event
End If
End While
You could also keep your ports in an array, and process them in sequence, so you’re only processing one message per pass through your loop.
“TheEndless” wrote:
The port is FIFO, so if you have one port, issuing a large number of texture requests can delay processing of other events. If you use two different ports, then your event loop can look something like this, so the large number of texture request events don’t delay other processing […] You could also keep your ports in an array, and process them in sequence, so you’re only processing one message per pass through your loop.
Makes sense very much, thank you! Keeping two ports allows you to selectively prioritize processing.
On a related note, I was wondering as a newbie in Roku dev - what are typical examples in which multiple components will be firing events (and will either be joined in single port or multiple ports polled in turn - no matter). Don’t need code sample, just kinds of combos coming to mind? I know i can search for ifSetMessagePort and mix&match them but am curious of typical things popping in real development. E.g. here is UI screen/dialog and roTextureManager - what else?
“EnTerr” wrote:
On a related note, I was wondering as a newbie in Roku dev - what are typical examples in which multiple components will be firing events (and will either be joined in single port or ports polled in turn). Don’t need code sample, just kinds of combos coming to mind? I know i can search for ifSetMessagePort and mix&match them but am curious typical things popping in real development. E.g. here is UI screen/dialog and roTextureManager - what else?
In addition to the above, the big one that comes to mind is asynchronous roUrlTransfer requests. A few examples… 1) you need to make multiple API requests to populate the rows of a grid screen, or 2) you want to make autocomplete requests to populate suggestions on your search screen, or 3) you need to make web-based analytics calls for UI and video events (you never want analytics to interfere with the operation of your channel).
In my own development I have a module where I am
Loading text files for a e-reader that I am working on. There is also a grid
That displays the books with graphic skins for each book
I use the async methods of urltransfer for the text and async texturerequests
For the graphics. I wrap these components in a class that creates
A separate port. While I generally use the same port for just about everything else
At least right now, It just seemed more thread like to keep asyncs
Seperate regardless of the magnitude and frequency of data being loaded. If I am
Polling asyncs to allow for a timeout then I use the common port
Since it is blocking anyway. I am even considering putting my roSystemLog
On its own port which is contraindicated but depending on the settings
It can generate a lot of Events.