I have a thread that handles a search in the background, and then sends found items for display via the thread user interfaceupdate mechanism. The Run code looks like this:
select case searchType
for i = 0 to ubound(myProject.pageStrings)
j = instr(myProject.pageStrings(i),searchString)
if j > 0 then
d = new Dictionary
d.value(“type”) = searchType
d.value(“title”) = mid(myProject.pageStrings(i),j-50,100)
d.value(“link”) = myProject.curCaseFileName+"/"+str(i+1)
and the code in userinterfaceupdate looks like this:
while data.count > 0
However, userinterfaceupdate never fires. I can verify in the debugger that the AddUserInteraceUpdate in run does execute, and also with a breakpoint in userinterfaceupdate (Added via a dummy line before the WHILE to test) never fires.
Is it possible the thread run is so short that it finishes before userinterfaceupdate gets around to firing? Or is there something else that needs to be done to cause this event to fire?
betting that at the end of the thread they dont call the user interface update to make sure that any queued updates get run
Is that the entirety of the thread? If the thread exits after the
next, then all your dictionaries will go out of scope. Try adding a sleep (1000) after the
next to give a chance for the updates to be done before the thread exits. If that’s part of a larger bit of code for the thread, try a sleep just before the
So, I’m not sure about the dictionaries going out of scope (I’d expect some other issues), but I think you must need some sort of break in the thread, and putting in the line sleep(1,true) right before the next does fix the issue.
I guess there are a couple problems with this Xojo should consider:
- Not intuitive to have to break your thread yourself for this
- Per Norman’s suggestion, if a thread does run short, queued updates are just dumped? I’d suggest a warning in the docs to the effect that this is really only to be used for non-essential UI updates and not actually transferring data you don’t want to lose. I may have conflated the two purposes myself, since I’m using it for both.
me.AddUserInterfaceUpdate was added for threads, what one did previously was to have an array of actions, and then trigger a one-tick timer, and handle the array of actions in the timer’s action event. It was then that I found that for my threads, their final action to update the UI was not being done. That’s when I found that sleeping the thread for 1 sec as the last thing it did was enough to allow the final UI action to complete.
Not sure actually if dictionaries going out of scope matters, but then it shouldn’t have mattered for the array I mentioned above. But perhaps Xojo, in adding this feature, altered the way threads are terminated so that even the old method of handling UI updates would now work without the sleep (1000) being needed any longer. I’ll have to test it.
Anyway - glad it works for you
Indeed, I previously dumped output/updates into an array and then had a separate timer pick them up and deal with them. Thought I’d give this feature a go, but now I’m uncertain exactly how deterministic it is and whether I can really trust that I’ll ever get all of my data back from the thread. Probably go back to the old way for the data transfer.
The new approach provides an array of dictionaries to the event handler that does he UI updates. I make a pointer to the zeroth element, remove it from the array, and then handle it. At the thread-end dictionaries are added one at a time to the array by calling this new method, so it ought to be OK. It’s perhaps less critical for me as I’m not passing anything crucial in this fashion.
seems that the thread end should run one last UI update IF it still has queued items before its destroyed
otherwise you have this issue where queued updates do not get done
[quote=497483:@Norman Palardy]seems that the thread end should run one last UI update IF it still has queued items before its destroyed
otherwise you have this issue where queued updates do not get done[/quote]
I agree, though I can also see the logic that if this is just about UI updates during the thread run, after the thread run they all become irrelevant (as long as you weren’t depending on them for data transfer, of course). In this case, the documentation should probably provide some warning on this behavior.
By the way, I also tried moving the sleep statement to the very end of the thread (outside the for…next) to see if I could flush those events in the manner you’re suggesting, and it didn’t work. Which is why I’m leery about depending on this mechanism for data transfer in any way.
I tried to use UI update to tell my app when the thread was finished and what to do next, but because it didn’t do an update after the thread ended, I had to toss the idea. Waiting a second helped, but on a really slow machine it was unreliable.
And the very first call is almost never called. The thread class doesn’t ensure you get the data you want. Better make your own subclass with a timer and raise an event before and after run to flush your data (raise some event(s) when there is data).
Here you have a example it should still work and provide you with an example
I’ll check it out, thank you!