My Code is:
class Client(DirectObject, object):
'''
Clientclass. This class processes the keys which the user presses to the host and gets the data
from the host, which are to be set in a dummy version of the model
'''
seed= ""
id = None
def __init__(self, ip):
'''
This is the constructor. It creates the ShowBase an starts both the process which processes the keys and the process
which takes in data from the host
param: ip ip is a float which contains the ip adress of the host
'''
logging.getLogger(__name__).info("Clientobjekt erstellt")
self.makw = mouseAndKeyWrapper.MouseAndKeyWrapper()
time.sleep(5)
from modules.logic import game
self.cprocess = threading.Thread(target = Client.workAsClient, args = (ip,self.makw))
self.cprocess.start()
time.sleep(5)
while True:
if Client.seed != "":
break
game.seed = Client.seed
game.initGame()
game.initGameInstance()
game.start()
self.workShowBase()
game.myShowBase.run()
def workShowBase(self):
'''
workShowBase defines how to change values in keydict when keys are pressed and
starts ShowBase process
'''
from modules.logic import game
logging.getLogger(__name__).info("Showbase is working")
game.myShowBase.accept("w", self.makw.setKeys, ["w",1])
game.myShowBase.accept("a", self.makw.setKeys, ["a",1])
game.myShowBase.accept("s", self.makw.setKeys, ["s",1])
game.myShowBase.accept("d", self.makw.setKeys, ["d",1])
game.myShowBase.accept("space", self.makw.setKeys, ["space",1])
game.myShowBase.accept("w-up", self.makw.setKeys, ["w",0])
game.myShowBase.accept("a-up", self.makw.setKeys, ["a",0])
game.myShowBase.accept("s-up", self.makw.setKeys, ["s",0])
game.myShowBase.accept("d-up", self.makw.setKeys, ["d",0])
game.myShowBase.accept("space-up", self.makw.setKeys, ["space",0])
#game.myShowBase.accept("mouse1",self.makw.setKeys,["mouse",1])
#game.myShowBase.accept("mouse1-up",self.makw.setKeys,["mouse",0])
@staticmethod
def workAsClient(ip, makw):
'''
This method contains the client thread, that is, the thread which sends data to the host and
receives data from it - for this reason it has to be static
param: ip ip is a float which contains the ip adress of the host
'''
logging.getLogger(__name__).info("Clientendlosschleife gestartet")
from modules.logic import game
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, 50001))
seedSend = s.recv(4096)
Client.seed =loads(seedSend)
ID = s.recv(4096)
Client.id = loads(ID)
makw.id = id
keyThread = threading.Thread(target =Client.sendData, args = (makw,s))
print("threadmade")
keyThread.start()
print("started")
@staticmethod
def sendData(makw, sock):
print("method")
while True:
print("loop")
dictToSend = dumps(makw,2)
print("dumped")
sock.sendall(dictToSend)
print("sent")
That does work fine.
However, if I omitt "time.sleep(5)" in the constructor, the thread which calls sendData is never ever made, let alone be started. How can that be? Showbase technically should not interfere, being in another process! Can I fix this?
You should avoid using full active waiting that may consume all the resources letting no chance for other threads to work.
So you may better try :
while True:
if Client.seed != "":
break
time.sleep(10)
Indeed your secondary thread is launched but if all processing is consumed by your main thread in its infinite loop it will never have a chance to work, then never providing the seed for which the main thread is waiting => deadlock
When you use sleep(5) you give a chance to the secondary thread to be scheduled and to produce the seed; then when latter the main thread is rescheduled it finds the seed, continues working and all is going as expected.
But your workaround is very brittle because you have no guarantee that during the sleep of the main thread the other one will be scheduled.
It works now in your development environment but may break later in production in another context.