Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I properly run 2 threads that await things at the same time?

Basically, I have 2 threads, receive and send. I want to be able to type a message, and whenever I get a new message it just gets 'printed above the line I am typing in'. first what I thought would work, and you can just paste this it will run:

import multiprocessing
import time
from reprint import output
import time
import random
import sys

def receiveThread(queue):
    i = 0
    while True:
        queue.put(i)
        i+=1
        time.sleep(0.5)

def sendThread(queue):
    while True:
        a = sys.stdin.read(1)
        if (a != ""):
            queue.put(a)
        


if __name__ == "__main__":
    send_queue = multiprocessing.Queue()
    receive_queue = multiprocessing.Queue()

    send_thread = multiprocessing.Process(target=sendThread, args=[send_queue],)
    receive_thread = multiprocessing.Process(target=receiveThread, args=[receive_queue],)
    receive_thread.start()
    send_thread.start()

    with output(initial_len=2, interval=0) as output_lines:
        while True:
            output_lines[0] = "Received:  {}".format(str(receive_queue.get()))
            output_lines[1] = "Last Sent: {}".format(str(send_queue.get()))

But what happens here is that i cannot send data. The input doesn't give me an EOF unlike when I put a = input(), but it overwrites whatever I put in that line, so how can I wait for the input in one thread while the other one works?

EXPECTED BEHAVOIR:

first line goes Received: 0, 1, 2, 3, 4...

second line goes [my input until I press enter, then my input]

ACTUAL BEHAVIOR if i don't check if input != ""

first line as expected only that the input overwrites the first couple of letters until it resets to Received

second line is always empty, maybe bc stdin only is filled for that one time i press enter and then always returns empty?

ACTUAL BEHAVIOR if i check if input != ""

first line stays: received = 0

second line is just like whatever i enter, if i press enter it goes into a new line where i then enter stuff

like image 437
Maritn Ge Avatar asked Nov 24 '20 21:11

Maritn Ge


1 Answers

Don't use the same socket for communicating with... itself. That may be possible to do, I'm not sure, but it certainly isn't normal. Instead make a socket pair, one for the sending thread, and one for the receiving thread, e.g. this works for me:

import socket;
import multiprocessing;

def receiveThread(sock):
    while True:
        msg = sock.recv(1024)
        print(msg.decode("utf-8"))

def sendThread(sock):
    while True:
        # msg=input("client: ")
        # input() is broken on my system :(
        msg="foo"
        sock.send(bytes(msg,"utf8"))

pair = socket.socketpair()
recieve_thread_socket = pair[0]
send_thread_socket = pair[1]

send_thread = multiprocessing.Process(target=sendThread, args=[recieve_thread_socket])
receive_thread = multiprocessing.Process(target=receiveThread,args=[send_thread_socket])
send_thread.start()
receive_thread.start()
like image 100
hanshenrik Avatar answered Oct 08 '22 18:10

hanshenrik