GUI still locking up during Asynchronous Call

Hi Everyone,

I was hoping to get some input. I am trying to make an asynchronous call to the Gateway to read tag values. Below is the funtion:

	def readTags(tagPath)	
		for i in range(1, 15) + range(51, 65) + range(101, 115) + range(151, 165) + range(201, 215) + range(251, 265) + range(301, 315) + range(351, 365) + range(401, 415) + range(451, 465) + range(501, 515):
			print "here"
			recipe = % i)

I am then using PTurmel’s scripts to make the function call asynchronously and pass the tagPath argument.

rt1Path = "CIP_1/RT1/C2/C2_%d_"

shared.later.callAsync(readTags, rt1Path)

While the code is executing, the UI will lock-up, I am not sure if I am using this function correctly. Thanks in advance!

Thats weird. What kinds of things are after the callAsync() call? You’re reading all this, what are you doing with it?

Also just a note, I would really suggest making a list of tagPath % i in an array, then using system.tag.readAll() - in my experience, much faster than reading 1 at a time.

I am building a dataset with the results, but I actually commented out the rest of the code to verify where the hang up was, and it is in the for loop / read tags call.

Thanks for the reply.

Probably need to see the implementation of callAsync

See this link for these helpers. callAsync just constructs a function with the arguments in its closure and passes it to invokeAsynchronous().
The lockup is possibly related to using print from a background task, which is a forbidden UI operation. { Use a logger in the background, but only if you must. } However, each read() will make a gateway round trip. That might be interfering with normal polling for the UI. Try making both changes, one at a time.
You should never put read() in a loop like this anyways. Get them all in one call, then loop through the results separately.

Thanks for all the advice. I followed it, and I was able to speed things significantly. Mainly, placing the tag paths into a list and making a single call with the system.tag.readAll() method. Here is the code I ended up with.

from javax.swing import JScrollPane
table = event.source.parent.parent.getComponent('Step Table')

if event.propertyName == "selectedRow":

	table  = event.source.parent.parent.getComponent('Step Table')
	table.selectedRow = -1
	data = []
	header = ['index', 'stepNumber', 'intValue', 'stepDescription']

	def cip_path(circuitID):
		switcher = {
			0: "CIP_1/RT1/C2/C2_%d_",
			1: "CIP_1/RT2/C3/C3_%d_",
			2: "CIP_1/RT3/C4/C4_%d_",
			3: "CIP_1/RT4/C5/C5_%d_",
			4: "CIP_1/RT5/C10/C10_%d_",
			5: "CIP_1/LC1/C6/C6_%d_",
			6: "CIP_1/LC2/C7/C7_%d_",
			7: "CIP_1/LC3/C12/C12_%d_",
			8: "CIP_1/LC5/C9/C9_%d_",
			9: "CIP_1/LC10/C17/C17_%d_",
			10: "CIP_1/Cream_LineToM/C8/C8_%d_",
			11: "CIP_1/Tanker/C1/C1_%d_",
			12: "CIP_1/Tanker_Rinse_Only/C16/C16_%d_",
			13: "CIP_1/RT6/C11/C11_%d_",
		return switcher.get(circuitID, "Not Found")
	test = cip_path(event.source.selectedRow)
	dict = {
		0: "Not Running", 
		1:"Start Supply Pump", 
		2: "Pre-Rinse", 3: "Pump Down", 
		4: "Start Supply Pump", 
		5: "Water/Caustic Push", 
		6: "Caustic Wash", 
		7: "Pump Down", 
		8: "Start Supply Pump",
		9: "Caustic/Water Push", 
		10: "Rinse", 
		11: "Pump Down", 
		12: "Start Supply Pump",
		13: "Sanitize", 
		14: "Pump Down"
	tags = []
	for i in range(600):
		tags.append(test % i)	
	values = system.tag.readAll(tags)
	j = 0
	for i in range(len(values)):

		if j == 50:
			j = 0
		data.append([i, j, values[i].value, dict.get(i)])
		j = j + 1
	ds = system.dataset.toDataSet(header, data)
	event.source.parent.parent.getComponent('Step Table').data = ds

Consider putting your cip_path() function in a script module. You’re wasting time redefining it on every event. Also consider placing your dictionary of constants in a script module, but don’t name it dict. That’s a predefined function in python. Assigning to that name blocks access to the function in that scope.