【问题标题】:Python Tkinter Multithreading functionsPython Tkinter 多线程函数
【发布时间】:2013-06-01 02:26:31
【问题描述】:

我目前正在使用来自 python 的 tkinter 库来开发电子邮件发件人和接收程序。 我正在使用线程模块使程序每 60 秒刷新一次未读电子邮件,而您仍然可以继续在程序中执行操作。

线程模块只在发出 print("something") 命令时工作,我仍然可以继续在程序中做事。但是,当我将线程登录到 gmail 并获取未读电子邮件计数时,整个程序会冻结并崩溃。

下面是我的代码的 sn-p。我不会发布完整的代码,我做了一个简短的版本来展示它的外观。

编辑: 在功能上犯了一个小错误。 get_credentials() 被移除。

import tkinter, re, threading, time, imaplib, too many to list here.
class Application(Frame):

def __init__(self, parent):
        ... Start some functions
        ... Create some widgets
        ... Create some global stringvars for entry fields

def threadrefresh(self):#I want to start this function when a button is clicked

        def multithreading():

            usernamevar = "Username"
            passwordvar = "Password"

            obj = imaplib.IMAP4_SSL('imap.gmail.com', '993') #connect to gmail
            obj.login(usernamevar, passwordvar) #log in
            obj.select() #select the inbox
            unread = str(len(obj.search(None, 'UnSeen')[1][0].split())) #get the total unread
            print(unread)
            obj.close()

            time.sleep(3)
            multi = threading.Thread(target=multithreading)
            multi.start()

        multi = threading.Thread(target=multithreading)
        multi.start()

def other_functions_that_do_not_matter_in_this_case():
    ... Creating GUI
    ... Sending mail
    ... Etc.
    ... Create a button with function call self.threadrefresh


def main():
    root = Tk()
    app = Application(root)
    root.mainloop()

if __name__ == '__main__':
    main() 

【问题讨论】:

  • 也许 tkinter 不喜欢多线程。 Tkinter 带来了一个 Tk.after 方法,它在给定时间后调用一个函数。也许这已经符合您的需求。
  • @IchUndNichtDu 我更喜欢在后台运行一个线程。我在线程每隔几秒钟打印一个字符串时取得了一些成功,而我仍然可以使用我的程序。
  • Tkinter 做线程就好了。在 tk.Var 上使用 trace 方法。将其指向一个函数,该函数将某些内容添加到另一个线程搜索的队列中(请参阅我的答案。)

标签: python multithreading tkinter imaplib


【解决方案1】:

这段代码真的正确吗?

你在多线程中调用它:

time.sleep(3)
multi = threading.Thread(target=multithreading)
multi.start()

您基本上是在告诉每个线程在 3 秒后创建自己的副本...我认为您错过了线程的重点。您可能应该在 while 循环中运行一个(单个)线程,从 Queue 获取数据。

只要你想让线程对某事采取行动,就将它添加到队列中。

编辑:示例代码

import threading
import Queue
import time

def f(q):
    while True:
        print q.get() #block thread until something shows up

q = Queue.Queue()
t = threading.Thread(target=f,args=[q])
t.daemon = True #if parent dies, kill thread
t.start()
for x in range(0,1000):
    q.put(x)
    time.sleep(1)

【讨论】:

  • 好吧,我只是在后台运行线程后尝试了这个,没有再次调用自己。还尝试了一个带有 time.sleep 的 forloop。如果我不再次放入线程,我只是在最后再次调用该函数。编辑:虽然会尝试 Queue 方法。
  • 这绝对是要走的路(队列)。您只有一个 while 循环,顶部有 queue.get()。它将阻塞(线程),直到它获得数据。一旦它得到数据就可以用它做任何事情。完成后,它将循环返回并等待更多数据。
  • 谢谢!我真的不知道这个功能存在。每次收到新邮件更新时,我都会想起你 :)
  • 嘿,我一直在尝试使用 Queue 做一些事情,但在网上找不到 简单 的解释。我将如何构建这样的东西?
  • 可能是这样的:lonelycode.com/2011/02/04/… 我建议只编写一些测试代码来启动从队列中读取的线程。一旦你理解了这个原理,这真的很容易。
猜你喜欢
  • 2018-06-26
  • 1970-01-01
  • 2016-08-03
  • 1970-01-01
  • 2022-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多