I'm trying to switch from one thread called CameraProcessing to another thread called ServerKeypoints and viceversa. To be precise, CameraProcessing changes a global variable called VALUE while ServerKeypoints consumes the global value by sending it via websocket to a client. To protect the global variable I've used the Condition mechanism.
I have two problems:
- At a certain moment the script stucks, the threads don't go forward
- The websocket client doesn't receive the data sent via websocket
The two threads are located in a script called main_server.py (I know that it is not the best idea and that it would be better to split these threads in different files).
main_server.py
import threading
import asyncio
import websockets
condition = threading.Condition()
VALUE = 0
FLAG = 0
class ServerKeypoints(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
async def communicate(self, websocket):
global VALUE
global FLAG
while True:
condition.acquire()
if FLAG == 1:
FLAG = 0
print(f"SERVER VAL: {VALUE}")
await websocket.send(f"{VALUE}")
condition.notify_all()
else:
condition.wait()
condition.release()
async def main(self,):
async with websockets.serve(self.communicate, "localhost", 9998):
await asyncio.Future() # run forever
def run(self):
asyncio.run(self.main())
class CameraProcessing(threading.Thread):
def __init__(self) -> None:
threading.Thread.__init__(self)
def run(self):
global VALUE
global FLAG
while True:
condition.acquire()
if FLAG == 0:
VALUE = 1
print(f"CAMERA VAL: {VALUE}")
FLAG = 1
condition.notify_all()
else:
condition.wait()
condition.release()
While client.py is written in the following way:
import websocket
def on_message(wsapp, message):
message = message
print(message)
wsapp = websocket.WebSocketApp("ws://localhost:9998", on_message=on_message)
while True:
wsapp.run_forever()
In the Visual Studio Code terminal I have a result like this:
CAMERA VAL: 20301
SERVER VAL: 20301
CAMERA VAL: 20302
SERVER VAL: 20302
CAMERA VAL: 20303
SERVER VAL: 20303
CAMERA VAL: 20304
SERVER VAL: 20304
CAMERA VAL: 20305
SERVER VAL: 20305
CAMERA VAL: 20306
SERVER VAL: 20306
CAMERA VAL: 20307
SERVER VAL: 20307
CAMERA VAL: 20308
SERVER VAL: 20308
CAMERA VAL: 20309
SERVER VAL: 20309
CAMERA VAL: 20310
SERVER VAL: 20310
CAMERA VAL: 20311
SERVER VAL: 20311
CAMERA VAL: 20312
SERVER VAL: 20312
CAMERA VAL: 20313
SERVER VAL: 20313
But it does not go forward.
CodePudding user response:
As suggested by Michal Butscher in the comments, I've tried again the client script provided by the websockets module and I've modified in the following way:
import asyncio
import websockets
async def receive():
while True:
try:
async with websockets.connect("ws://localhost:9998", ping_interval=None) as websocket:
msg = await websocket.recv()
print(f"{msg}")
except:
continue
if __name__ == "__main__":
asyncio.run(receive())
Now it doesn't stuck.
I know that the combination async and thread is not a good idea but if you have alternatives to propose I will be glad to read them.
CodePudding user response:
I've used threads because they share the global variable VALUE and in order to protect it I use thread locks like Condition.
OK, but you don't need to create threads in order to use global variables. Your ServerKeypoints
thread and your CameraProcessing
thread never do any interesting thing concurrently with each other, so why not just have one thread that does this?
async def communicate(self, websocket):
global VALUE
while True:
VALUE = 1
print(f"CAMERA VAL: {VALUE}")
print(f"SERVER VAL: {VALUE}")
await websocket.send(f"{VALUE}")
Get rid of the condition
, get rid of the FLAG
, get rid of the threads. It's a whole lot simpler, and (I'm pretty sure) it will do the same as what your example code does.