tag.writeALLSynchronous?

Hey all!
Is there a writeAllSynchronous Function available?
My problem is I use two writeall commands to write about 400 tags to my plc, I then write some specific identifying information about the tag set to 4 tags synchronously, then I write a zero to my hand shake bit to tell the PLC I am ready for it to process the data. The synchronous writes make sure the 4 identifying tags write before the hand shake, but the problem is I need to be able to make 100% sure that my writeall has finished as well before I flip the hand shake. I call all of my scripting from an event on a text box that the user scans into, that then goes out to multiple app.xxxxx modules depending on evaluations. I have already wrapped the synchronous tag writes with a system.util.invokeAsynchornous which contains my handshake at the end. I think my solution lies within the system.util.invokeAsnynchronous and the system.util.invokeLater, however I am still foggy on how they work. Do I just need to wrap my hand shake with the system.util.invokeLater? Will that script wait to run until all of the tag writes previously called complete?

For instance:
( I have added numbers next to the lines of code in the order they must execute.

1#app.writemytagblock
3#def writeidtags():
4# system.tag.writeSynchronous(idtag1)
5# system.tag.writeSynchronous(idtag2)
7#def writehandshake():
8# system.tag.write(handshaketag)
2#system.util.invokeAsnynchronous(defwriteidtags)
6#system.util.invokeLater(writehandshake)

Now its very possible that I am doing this in a much more difficult manner than is necessary, but it is imperative that I know that all of my tags have finished writing before I do the handshake.

If anyone has some hints or additional information about the invokeLater function I would love to hear it.
Thanks,
-Shawn

Hi Shawn,

Inside a Python script you cannot be sure of when system.tag.writeAll or system.tag.write will complete writing to all the tags they are given. So if you need to be sure that tags are written to before you do something else then do not use system.tag.writeAll or system.tag.write.

To understand this, here is what is happening: A call to system.tag.writeAll or system.tag.write returns immediately – which means that when a script is executing and it sees one of these it calls it but does not wait for it to execute. The script continues processing right past the system.tag.writeAll or system.tag.write calls. The actual execution and writing to tags is done in a separate thread of execution which you do not control. That is why system.tag.writeSynchronous exists – this function executes in the same thread of execution as your script and it does not return until it writes a value to a tag or it throws a timeout exception.

The problem with using system.tag.writeSynchronous is that if you need to write to many tags, like 400, it can take a long time. I agree that having a system.tag.writeAllSynchronous would be very nice. Also system.tag.writeSynchronous can only be called within a non-GUI thread such as function that is executed with system.util.invokeAsynchronous. The system.util.invokeAsynchronous function is passed a function as an argument and executes that function in another thread.

If system.tag.writeSynchronous could be run in the GUI thread and a user pressed a button and system.tag.writeSynchronous started to write to 400 tags the GUI would freeze and the user would become unhappy. That’s why I think system.tag.write and system.tag.writeAll exist. They actually execute in a different thread so they return right away in our scripts and so keep the GUI very fast.

system.tag.write can be simulated by calling system.tag.writeSynchronous in a function that is executed by the system.util.invokeAsynchronous function. With this approach you get the advantages of both system.tag.write and system.tag.writeSynchronous.

The system.util.invokeLater function really has nothing to do with writing to tags. A function that is executed with system.util.invokeAsynchronous should use system.util.invokeLater in places where it interacts with the GUI.

Here is an example that writes some tags in a specific order. You can be sure that each tag write happens before the next:

def writeTagsInOrder():
	import system
	system.tag.writeSynchronous("test1",5)	
	system.tag.writeSynchronous("test2",5)
	system.tag.writeSynchronous("test3",5)
	system.tag.writeSynchronous("test4",5)
	system.tag.writeSynchronous("test5",5)
	system.tag.writeSynchronous("test6",5)
	system.tag.writeSynchronous("test7",5)

system.util.invokeAsynchronous(writeTagsInOrder)

Nick’s information is all correct. I’d just like to add that we will be adding a system.tag.writeAllSynchronous shortly (7.7.1 timeframe)

That’s awesome. Do you have an idea of how system.tag.writeAllSynchronous would work yet?

Would it be passed a list of paths and a list of values like the system.tag.writeAll function?

Would it write tags synchronously based on the order of the tags in the list – or would it execute them in any order but system.tag.writeAllSynchronous won’t return before they are all written?

It will work similarly to writeAll, except that it won’t return until all writes have either completed or failed.

Write order is not up to us - it’s up to the underlying OPC server. If you need strongly ordered writes then you should not use any variant of writeAll

That makes sense. Thanks!

[quote=“nmudge”]
If system.tag.writeSynchronous could be run in the GUI thread and a user pressed a button and system.tag.writeSynchronous started to write to 400 tags the GUI would freeze and the user would become unhappy. That’s why I think system.tag.write and system.tag.writeAll exist. They actually execute in a different thread so they return right away in our scripts and so keep the GUI very fast.[/quote]

Hey Nick,
Thanks for the explanation. My problem is that I WANT the gui to freeze until the tags are finished writing. The client that writes these tags has only 1 task, and that is to process this data, and write the tags to the PLC. I just have to be sure that the PLC does not get the handshake until the mass tag write is completed. I also have to be sure that if the client is running slow, or hangs that the user can not trigger the event again until the process has first completed.
Right now I am doing this, and have not been able to break it.

app.dosomethingswithdb system.tag.write("STEPINSTRUCTION", "") window = system.gui.getWindow("SCAN ENTRY") inscan = window.rootContainer.getComponent("INSCAN") waitlbl = window.rootContainer.getComponent("writetoplclbl") inscan.enabled = False waitlbl.visible = True def finaltagwrites(): app.SENDDATATOPLC.MassTagWritealls() if TOMANYREC == 0: system.tag.writeSynchronous("IDTAG1", ID1) system.tag.writeSynchronous("IDTAG2", ID2) system.tag.writeSynchronous("IDTAG3", ID3) system.tag.writeSynchronous("IDTAG4", ID4) system.tag.writeSynchronous("IDTAG5", ID5) def finishsteps(): system.tag.write("PLCHS", 0) app.writesuccess() app.playfinishsound() window = system.gui.getWindow("SCAN ENTRY") inscan = window.rootContainer.getComponent("INSCAN") waitlbl = window.rootContainer.getComponent("writetoplclbl") inscan.enabled = True waitlbl.visible = False system.util.invokeLater(finishsteps) if TOMANYREC == 1: app.SCANFAIL.valfail() window = system.gui.getWindow("SCAN ENTRY") inscan = window.rootContainer.getComponent("INSCAN") waitlbl = window.rootContainer.getComponent("writetoplclbl") inscan.enabled = True waitlbl.visible = False system.util.invokeAsynchronous(finaltagwrites)

Its prevents the operator from being able to scan in another order unless the process has finished, however it still does not mean that my mass tag writes have all finished before I write the hand shake.

I can totally understand wanting to lock the operator out of doing an action while the write is taking place, but freezing the UI to achieve this is not the way to go. Nobody likes a frozen UI - it feel awful and you get no feedback as to what’s going on.

Instead, (like you’re already doing), first disable the relevant parts of the UI, show some sort of “write in progress…” message, and then only re-enable after it’s done.

[quote=“Carl.Gould”]I can totally understand wanting to lock the operator out of doing an action while the write is taking place, but freezing the UI to achieve this is not the way to go. Nobody likes a frozen UI - it feel awful and you get no feedback as to what’s going on.

Instead, (like you’re already doing), first disable the relevant parts of the UI, show some sort of “write in progress…” message, and then only re-enable after it’s done.[/quote]
Yeah your probably right about the gui, although I don’t care if its frozen, I don’t care if it isn’t either as long as they can’t break it.

Good to know there will be a writeAllSynchronous soon. For now I am just running a delay timer on the hand shake and giving the tags a couple seconds to update before I start processing. So far I haven’t had an issue, but there is always that chance.

Thanks for all of the help!