Can't Put PV value from multiple Process
Closed this issue · 2 comments
Dear All,
I try to create some PVs using pythonSoftIOC, and also create an another process to get/put the defined PVs. The code runs successfully, but the results are not corrected!(The two PV's values should be same). And I open another terminal to get the PV values, their are just the initialized ones in the builder procedure.
I don't know way, and whether it is ok using the multiple process to get/put PVs. Thanks a lot for your help and suggestions!
The result from another terminal:
Best regards,
Jiyizi
I've never actually used pyepics, but I have reproduced your issue. I think the problem is that cothread
doesn't work when multiprocessing Processes are spawned after it is imported. I'm not quite sure why. There are 2 possibilities:
- Use
cothread.Spawn
andcothread.catools.caget
rather thanmultiprocessing.Process
andepics.PV.get
- Move the multiprocessing call before
iocInit
, as this does an implicitimport cothread
An example of 1:
# Import the basic framework components.
from softioc import softioc, builder
import cothread
from cothread.catools import caput
# Set the record prefix
builder.SetDeviceName("MY-DEVICE-PREFIX")
# Create some records
ai = builder.aIn('AI', initial_value=5)
ao = builder.aOut('AO', initial_value=12.45, always_update=True,
on_update=lambda v: ai.set(v))
# Boilerplate get the IOC started
builder.LoadDatabase()
softioc.iocInit()
# Start processes required to be run after iocInit
def update():
counter = 0
while True:
counter += 1
caput("MY-DEVICE-PREFIX:AO", counter)
cothread.Sleep(1)
cothread.Spawn(update)
# Finally leave the IOC running with an interactive shell.
softioc.interactive_ioc(globals())
An example of 2:
# Import the basic framework components.
from multiprocessing import Process
import time
from softioc import softioc, builder
def update():
from epics import PV
time.sleep(10)
a = PV("MY-DEVICE-PREFIX:AO")
# Why do you have to make this twice?
a = PV("MY-DEVICE-PREFIX:AO")
counter = 0
while True:
counter += 1
a.put(counter)
time.sleep(1)
p = Process(target=update)
p.daemon = True
p.start()
# Set the record prefix
builder.SetDeviceName("MY-DEVICE-PREFIX")
# Create some records
ai = builder.aIn('AI', initial_value=5)
ao = builder.aOut('AO', initial_value=12.45, always_update=True,
on_update=lambda v: ai.set(v))
# Boilerplate get the IOC started
builder.LoadDatabase()
softioc.iocInit()
# Finally leave the IOC running with an interactive shell.
softioc.interactive_ioc(globals())
Dear Coretl,
Thanks for your help! I have tried your suggestion, and it worked.
For me, the second method is preferred, since more CPUs can be used now.
Best regards,
Jiyizi