Threads, how to...

Hi, I’m using a command from MBS to calculateDirectorySize in a thread, but I always get a warning in my app that this is not legal to alter the main interface from a thread… but where do I alter it ? here is my threadcode in the run.

Dim f2 as folderItem
f2 = app.gDragger.FolderItem // app.gDragger is a global property of a dragitem which is a folderItem, tried to move it to app, but no help.

dim d as DirectorySizeMBS
d = f2.CalculateDirectorySizeMBS(True,0)

app. gSizeNo = d.LogicalTotalSize/1000000000

So now I run a timer to check if the thread is done, and that one is supposed to check the gSizeNo (a global property)….

How am I doing something illigal ?


I suggest you to move this question from General to Add-Ons, and change the topic to “CalculateDirectorySizeMBS on thread problem” so it can call the attention of MBS (Christian) more easily.

As of Xojo 2013r1 (I think) accessing the GUI from within the context of a thread will raise an exception.

Your solution using a timer will work, and using timers triggered by threads is the recommended way for threads to modify the GUI. It’s always safe to access the GUI in the Action event of any timer.

Andrew, look at the code, no direct CUI access. Maybe something inside the MBS method? So, shouldn’t MBS take a look?

It could be MBS, but that call to f2 = app.gDragger.FolderItem looks suspiciously GUI-related.

IN a thread, please pass a different value for ticks parameter to CalculateDirectorySizeMBS. Passing 0 zero disables the yielding.

Also if you get the exception, you should see where it is.
Maybe you access a control somewhere.

Hi, the f2= app.gDragger.FolderItem is for having a property at app level for storing the dragged folder. Is this still the main gui ?

I’ve tried to have all variables/properties, as global at app level, but the same happens here as on a window level.

I also tried to have ticks as 50 still no go.

new code is:
Dim f2 as folderItem
f2 = app.gDragger.FolderItem

dim d as DirectorySizeMBS
d = f2.CalculateDirectorySizeMBS(True,50)

app.gSizeNo = d.LogicalTotalSize/1000000000

and this is the code thats gets the dropItem:
if index = 0 then

dim f as folderItem
f = obj.FolderItem

Sizes(0).text = "calculating...."
path(0).text = f.NativePath//"Dropper"

if f.Directory then

  app.gDragger = obj
  Timer_Calc.mode = Timer.ModeMultiple
  msgBox "Not a directory or disc...."
end if

end if

could it be that the thread itself is in Window1 ? Does it has to be in a module ?

The problem is in the Thread… the first line:

app.gFolderItem = app.gDragger.FolderItem

But, both of these are at app level and not at window1 level. So not in the mainGUI ?

I can’t see how this code is trying to manipulate UI element….


I don’t know, I would consider reading non computed properties a non GUI intrusion. Bug?

Is the “app.gFolderItem” only accessed by your thread? You are setting it in a non protected way against concurrent access.

[quote=41496:@Helge Tjelta]app.gFolderItem = app.gDragger.FolderItem

But, both of these are at app level and not at window1 level. So not in the mainGUI ?

I can’t see how this code is trying to manipulate UI element….[/quote]

Accessing a DragItem from a thread will raise a ThreadAccessingUIException. While only a Xojo engineer can say for certain, I’d conjecture that the DragItem class is explicitly checking whether it’s running on the main/GUI thread and raising an exception if not.

Thanks Andrew, that solved it. Now I just used a string for nativepath, and lower the ticks in the MBS command to 3. Now it worked.
Now I can even run sliders up and down, while the command is calculating all foldersizes on my disc.


It is.