【问题标题】:How can I properly run 2 threads that await things at the same time?如何正确运行同时等待事物的 2 个线程?
【发布时间】:2021-03-07 17:30:55
【问题描述】:

基本上,我有 2 个线程,接收和发送。我希望能够输入一条消息,每当我收到一条新消息时,它就会“打印在我正在输入的行上方”。首先是我认为可行的方法,您只需粘贴它即可运行:

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()))

但是这里发生的是我无法发送数据。与我输入 a = input() 时不同,输入不会给我一个 EOF,但它会覆盖我在该行中输入的任何内容,所以我如何在一个线程中等待输入而另一个线程工作?

预期行为:

第一行已收到:0、1、2、3、4...

第二行是[我的输入直到我按下回车,然后是我的输入]

如果我不检查 if input != "" 的实际行为

第一行正如预期的那样,只是输入覆盖了前几个字母,直到它重置为 Received

第二行总是空的,也许 bc stdin 只填充了一次我按回车然后总是返回空?

如果我检查if input != "",实际行为

第一行停留:received = 0

第二行就像我输入的任何内容一样,如果我按下回车键,它会进入一个新行,然后我输入内容

【问题讨论】:

  • s 是什么?是插座吗?您使用的是什么库/包?
  • @MaritnGe 请阅读How to Ask并提供minimal reproducible example
  • 请将您的问题edit 提供给minimal reproducible example。请注意,您不是在使用线程,而是在使用进程。后面的错误还表明您的问题是从标准输入读取,而不是线程/进程或套接字。
  • 请注意此问题的当前迭代存在语法错误。即使没有,它实际上也没有产生任何输出;两个队列只是无限地积累数据,直到内存耗尽。
  • 这是一个通用的 I/O 事情,并不特定于 Python。阅读stdin/stdout standard streams 并从那里开始工作可能会有所帮助。老实说,这并不是最适合初学者的话题。

标签: python input command-line-interface python-multiprocessing


【解决方案1】:

不要使用同一个套接字与...自身通信。这可能是可能的,我不确定,但这肯定是不正常的。而是制作一个套接字对,一个用于发送线程,一个用于接收线程,例如这对我有用:

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()

【讨论】:

  • 这里的套接字是 tcp 套接字而不是线程套接字,如果您单击顶部的链接,您会看到我实际上是如何使用 multiprocessing.Socket 进行操作的,还是使用套接字对?
  • @MaritnGe 没有“线程套接字”之类的东西,但是 socketpair() 在 unix 系统上创建一个 unix 套接字(因为 unix 套接字比 tcp 套接字快),并在 Windows 上创建一个 tcp 套接字(因为 Windows 不支持 unix 套接字),并且使用 unix 套接字或 tcp 套接字并不重要,除非您计划传输大量数据,或者需要非常高的速度,在这种情况下它确实问题..无论如何,我投票结束你的问题needs shortest code necessary to reproduce the problem
  • 我会调查的,谢谢!是的,回想起来这是一个糟糕的问题,我只是不想删除它,所以我完全重写了另一个。感谢您对 python 和 SO 的建议
  • 与自己交流是什么意思?我正在使用这个套接字作为我和我的服务器之间的连接,我应该为我的服务器获取两个 tcp 连接到 lsiten 并发送吗?
  • @MaritnGe 似乎您的原始代码使用 1 个名为 s 的共享变量进行发送和接收。这不起作用,而是为您的接收线程获取 1 个唯一套接字,为您的发送线程获取另一个唯一套接字,并且这 2 个套接字必须相互连接。 (socketpair() 生成 2 个相互连接的唯一套接字)
猜你喜欢
  • 1970-01-01
  • 2013-03-18
  • 1970-01-01
  • 1970-01-01
  • 2010-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-26
相关资源
最近更新 更多