Refresh dataset

Can you explain exactly how the system.db.Refresh() is supposed to work? I assumed it would refresh immediately, but maybe I’m doing something wrong. Here is some sample code (one of the column names in the dataset is “Monitor”, and the name of the dataset is “Update” and is a dynamic property of the root container):

print pds[0]['Monitor']

system.db.runUpdateQuery("UPDATE IOStatus SET Monitor = Monitor + 1 WHERE MachineID = 1020")

print system.db.runScalarQuery("SELECT Monitor FROM IOStatus WHERE MachineID = 1020")

table = event.source.parent

print pds[0]['Monitor']

This is on a ‘button press’ event, and for instance it will return 9,10,9 for the first click, and 10,11,10 for the second. I have polling turned off on the dataset, so I know it’s the refresh function that is updating the dataset, but I would have thought it would take effect immediately. Is this how it’s supposed to work?

The system.dataset.refresh will re-run the query on the property you are refreshing. It does this asynchronously so it may be some time (depending on the query) for that to return. In your script the next line you will most likely have the last dataset before the refresh. If you want to wait for that refresh to complete you need to run a system.util.invokeLater for the last print out:[code]pds=system.dataset.toPyDataSet(event.source.parent.Update)
print pds[0][‘Monitor’]

system.db.runUpdateQuery(“UPDATE IOStatus SET Monitor = Monitor + 1 WHERE MachineID = 1020”)

print system.db.runScalarQuery(“SELECT Monitor FROM IOStatus WHERE MachineID = 1020”)

table = event.source.parent

def doLater(event=event):
print pds[0][‘Monitor’]
system.util.invokeLater(doLater)[/code]The invokeLater waits for the bindings to finish.

Thanks Travis, and also for your help on the phone yesterday. This is all much clearer now.

I think what was confusing me is the description of “invokeLater”. In the docs, it says “Invokes (calls) the given Python function object after all of the currently processing and pending events are done being processed”. But in practice, it seems to do the opposite, before the pending events are done, which is why I wanted to use it in the first place. So, just to get my hands around this, can you walk through this code?

def doAsynch(event=event):
	import system
	for i in range(1,1000):
		j = i*25		
		def doLater(event=event, j=j):
			event.source.parent.getComponent('Label').text =str(j)

The “doAsynch” is on a different thread, right? Is “doLater” on the same thread, or on the GUI thread that doAsynch was called in? Or is it on a third thread? Just want to understand this.

The doAsynch is on a separate thread. When you do an invokeLater that function runs back on the GUI thread after all [del]bindings[/del] events have finished. That is why you can alter the screen on the doLater - because it is on the GUI thread. So all in all there are only two threads the GUI and the new one for the asynch function.

Can you explain why you had the perception that doLater invokes things before events are processed, not after? That is certainly not the case. But do realize that events are not the same thing as bindings. Totally unrelated.

Ok, imagine I have a button, and on the button-pressed script, I start a loop that writes the following to a text box:

“This is line 1”
“This is line 2”
“This is line 3”

“This is line 1000”

If I don’t use invokeLater, the text box will not be populated until the loop is finished, along with the rest of the code in the event. But if I do use invokeLater, it populates immediately as the loop is processed. That’s where the confusion comes from. But all is good now. :slight_smile: