Accessing UI elements from a Thread using events

[quote=112590:@Norman Palardy]There are some things to still deal with BUT this is a pattern you can use fairly readily

[code]Class MyThread
private mTimer as Timer

   Event Definition DoMyStuff

   Sub Run()
          mTimer = new Timer
           AddHandler mTimer.Action, AddressOf timerCallback
           mTimer.Period = 20
           mTimer.Mode = Timer.ModeMultiple
           
           // now do whatever in my run event
           for i as integer = 0 to 10000000

           next
   End Sub

   Private Sub timerCallback(which as Timer)
         RaiseEvent DoMyStuff
   End Sub

End Class
[/code][/quote]
Xippet time?

This is fine for setting… but getting? Imagine a listbox with 100.000 rows and 12 columns where you have to set and get rows? Yes, you can do that with a timer but what a hack. Mirroring the listbox into an array, another hack… I am not complaining, just doing a research of what route I have to follow.

Or, you could do it on the main run loop instead of in a thread and not worry about it.

Then DONT TOUCH the UI elements from the thread
Have each thread get / set an object that is the data the listbox row displays
You can change that from a thread as much as you want and the listbox can grab the data & display it as needed as its just the data in a row tag object

The best (in my case) would be to maintain an array and ‘mirror’ all the listbox row data to it. I would then access the array, not the listbox itself. Is there an easy way to do that? Apart from manually add code where I add rows or modify cells?

Given the size of your listbox, any general mirroring will be slow. Maybe the ListBox.Change could enable you to do that in a more optimized way, and maybe a MyAddRow() method that updates the array and calls a timer to AddRow() at the same time ? It should be light enough to implement with a simple search/replace for AddRow, and the necessary code in ListBox.Change.

No easy way - you write code

To add a row you add a row to the “data row” or whatever you call it and then when you add a row to the overall “data” object it adds arrow to the list box when you add a row to the “data” object.
To edit you can use the edit cell but the events set the data back in the “data row” object.

Separating “the data” from its “presentation” is a good idea anyways because then you can alter the presentation without having to rework how the data is held. Often when you use the listbox for holding the data itself you have to rework things if you change the presentation. What used to be in one column is now in a different and so you have to go through all the logic & revise it because of this change.

If you have a “data row” object for each row then the ONLY thing you change is the presentation code because the underlying data hasn’t been reorganized or changed.

Just wondering, in the code:

[code]Class MyThread
private mTimer as Timer

   Event Definition DoMyStuff

   Sub Run()
          mTimer = new Timer
           AddHandler mTimer.Action, AddressOf timerCallback
           mTimer.Period = 20
           mTimer.Mode = Timer.ModeMultiple
           
           // now do whatever in my run event
           for i as integer = 0 to 10000000

           next
   End Sub

   Private Sub timerCallback(which as Timer)
         RaiseEvent DoMyStuff
   End Sub

End Class[/code]

shouldn’t we stop and close the timer at run() end? I mean a running timer couldn’t prevent a thread to be cleared from memory? I implement that code last week and users report my app slowing down after a while… just wondering…

[quote=182024:@Stanley Roche Busk]
shouldn’t we stop and close the timer at run() end? I mean a running timer couldn’t prevent a thread to be cleared from memory? I implement that code last week and users report my app slowing down after a while… just wondering…[/quote]
You should remove the handler

[code] mTimer = new Timer
AddHandler mTimer.Action, AddressOf timerCallback
mTimer.Period = 20
mTimer.Mode = Timer.ModeMultiple

           // now do whatever in my run event
           for i as integer = 0 to 10000000

           next
           RemoveHandler mTimer.Action, AddressOf timerCallback[/code]