我有一个虚拟的opcua服务器,它随机生成值。我创建了一个客户端,它必须从服务器读取值,每隔10秒,它应该将这些值存储在日志文件中。由于服务器非常快,在阅读值10秒后立即存储数据可能会导致延迟客户端读取服务器新生成的数据。这就是为什么我考虑使用多线程。
我设置了两个线程:一个线程用于阅读客户端,第二个线程用于存储数据。
线程的工作方式如下:首先,代码需要从客户端读取,一旦10秒的周期完成,存储数据的线程被触发,但它不应该中断另一个线程的阅读。
from opcua import Client
import time
from datetime import datetime
import threading
class client:
def __init__(self, url="opc.tcp://127.0.0.1:8080", store_cycle = 10, read_cycle=1):
self.url = url
self.store_cycle = store_cycle
self.read_cycle = read_cycle
def connect_to_server(self):
clt = Client(self.url)
clt.connect()
var1 = clt.get_node("ns=2;s=var1_val")
var2 = clt.get_node("ns=2;s=var2_val")
return var1,var2
def read_from_client(self,var1,var2):
iterator = 0
logs = []
dt = datetime.now().strftime("%Y-%m-%d_%Hh%Mm%Ss")
while iterator < (self.store_cycle/self.read_cycle):
iterator+=1
val1 = var1.get_value()
val2 = var2.get_value()
time.sleep(self.read_cycle)
logs.append(f"datachange_notification ns=2;s=var1_val {val1}")
logs.append(f"datachange_notification ns=2;s=var2_val {val2}")
print(val1)
print(val2)
print("log created")
return logs,dt
def store_values(self,logs,dt):
with open(f"logs/message_{dt}.log", 'w+') as logfile:
logfile.write('\n'.join(logs))
time.sleep(10)
c = client()
var1,var2 = c.connect_to_server()
while True:
t1 = threading.Thread(target=c.read_from_client, args=(var1,var2))
logs,dt = t1.run()
t2 = threading.Thread(target=c.store_values, args=(logs,dt))
t2.run()
这是我目前为止的方法,但我对多线程只有很少的经验。有什么帮助吗?
1条答案
按热度按时间kh212irz1#
我看到这里有一些问题。可能还有其他问题。我没有太深入地研究你想做的事情。
你调用
t1.run()
和t2.run()
。这通常是一个错误。你的主程序不创建任何线程。它创建了两个Thread
* 对象,* 但这不是一回事。如果你不调用t1.start()
和t2.start()
,实际上不会创建任何线程。当您调用
start()
函数时,它会创建一个新线程,然后 new thread 调用run()
函数。你的
t1.run()
函数返回一个值。但是当你start
一个单独的线程时,run()
函数返回的值将被忽略。如果你需要从一个线程到另一个线程传递一个值,你必须通过改变两个线程都可以访问的变量的值或对象的状态来完成。在
store_values
函数中没有循环,并且您只尝试调用该函数一次。因此,它只会调用logfile.write('\n'.join(logs))
* 一次。*我设置了两个线程:一个线程用于阅读客户端,第二个线程用于存储数据。
我只需要一个线程就可以完成,而不是每次循环都盲目地休眠10秒,我会 * 计算 * 休眠的时间,这样它就可以精确地每10秒从客户端读取一次。类似于下面的代码(伪代码):
如果“正确的时间”是大约1毫秒或更短的窗口,那么您可能希望在运行专门的real-time operating system的专用硬件上运行。如果窗口为几十毫秒或更长,那么您可能可以使用普通的桌面或服务器操作系统,但您可能仍然希望在专用硬件上运行(即,在没有同时运行其他程序的计算机上。)