Is it possible to know how many Threads are in the Application

I’d like to do a loop among the Threads I have in my App, but I don’t know how to do it.
I’d like something like:

For each TH as Thread in AllMyThreads ... ... Next
Can anyone tell me how to do it?
Thanks a lot.

I’m not sure there’s a way (be interested in knowing that I’m wrong, though).

I implemented a thread dictionary. Each thread registers itself in the dictionary at startup and when it terminates or is killed it unregisters. So now I have another thread which can list my threads and show some info about them.

I also believe that there’s no way to enumerate over all Xojo threads unless you’d use Introspection - but that would lead to very poor performance and may be unreliable.

Do that Tim suggests. The easiest way would be to make a subclass of Thread called “MyThread” that declares a shared property “allThreads as Dictionary”, add a new Event named “Run” to it, and in its own Run event do this:

Event Handler Run() allThreads.Value (self) = true RaiseEvent Run() Finally allThreads.Remove (self) End

By using “finally”, you ensure the thread gets removed from the dictionary even if the called thread code raises an exception.

Then find all your Thread classes and controls and change their Super to “MyThread”

Now, when you want to iterate over all threads, just do a “for each t as Thread in MyThread.allThreads.Keys”.

Thanks Tim and Thomas,
I think you are right and I will consider your advice. Anyway I raised a Feature Request:

feedback://showreport?report_id=60790

you could add and remove in Method Constructor & Destructor Me to a Global list AllMyThreads
in a class with Super set to Thread. its easy.
and the same just for counting objects you can do this with a shared property at this class.

you can definitely find how many are running

Dim o As Runtime.ObjectIterator = Runtime.IterateObjects
While o.MoveNext
  
  If o.Current IsA Thread Then
    // do whatever it is you need to know about the thread
  End If
  
Wend

see our blog post from 2 years ago:

Query all threads in Xojo app

[quote=494969:@Norman Palardy]you can definitely find how many are running

[code]
Dim o As Runtime.ObjectIterator = Runtime.IterateObjects
While o.MoveNext

If o.Current IsA Thread Then
// do whatever it is you need to know about the thread
End If

Wend
[/code][/quote]
Might that be expensive, perhaps? If you have a lot of objects, I mean.

I suppose …

Make your own thread list.

When your thread starts, add it to an array as weakref. On completion remove the weakref from the array. This way, if something goes wrong and the thread dies, it won’t be held in memory by your thread list.

[quote=494969:@Norman Palardy]Dim o As Runtime.ObjectIterator = Runtime.IterateObjects
While o.MoveNext[/quote]

i guess this style was before we got for each at arrays or is someone capable to write this as For Each?

Object iterator in runtime module is slow as it checks for each object via introspection the class and filters some internal stuff.

[quote=494957:@Markus Rauch]you could add and remove in Method Constructor & Destructor Me to a Global list AllMyThreads
in a class with Super set to Thread. its easy.
and the same just for counting objects you can do this with a shared property at this class.[/quote]

[quote=494957:@Markus Rauch]you could add and remove in Method Constructor & Destructor Me to a Global list AllMyThreads
in a class with Super set to Thread.[/quote]
Would you be able to do that in a Destructor? Docs seem to indicate that the Destructor is not called until there are no more references to the object - the thread in this case. How, then, could a Destructor have a reference to the thread that it then needs to remove from the Dictionary?

You need to keep WeakRef objects for them to avoid holding a reference.

documentation.xojo.com/api/language/weakref.html

Public Sub Constructor()
  ThreadList.AddRow New WeakRef(Me)
End Sub

Public Sub Destructor() For Each w As WeakRef In ThreadList If w.Value Is Me Then ThreadList.RemoveRowAt(ThreadList.IndexOf(w)) Exit End If Next End Sub
Global in Modul

Public Property ThreadList() as WeakRef
the .Value in WeakRef hold the Thread Object
and without removing at Destructor .Value would be Nil.

WeakRefs are not needed if you implement my solution, as it’ll take care of removing the circular reference even if the threaded code crashes.

Personally I’d keep a reference to the threads and not have to do runtime object checks
But the question was “Is there a way?” - yes there are several
I gave one

dice :slight_smile:

Thanks to all of you.
I’ve learnt a lot with this “thread”
In fact I wanted to implement this in a quite big and old application, so doing something when I create the thread seems to be the best option, but doing it without knowing at all how many threads (may be none) exist is a very interesting option for me, even if it is slow.

I’ve tested one of my Apps. In the App.Close event I put this code:

[code]Var i As Integer = Runtime.ObjectCount - 1

Var m As Integer = System.Ticks
For j As Integer = 0 To i
Var t As String = Runtime.ObjectClass(j)
If t.IndexOf(“Thread”) <> -1 Then Break
System.DebugLog t.Trim
Next j
m = System.Ticks - m
System.DebugLog Str(m)[/code]
There were 1064 objects and the time to check all of them and write their class name in the DebugLog, “m”, was only 2 ticks, and there was no Thread among them.