用Python创建你第一个GIS程序[5]:多进程解决线程堵塞

前言:在上一章中,我们将前后端连接起来,算是真正把程序给创建了出来。但是存在一个问题:当你点击“运行”按钮运行程序后,再用鼠标点击拖动 GUI 界面就会卡死...线程堵塞

当点击“运行”按钮运行程序后,再用鼠标点击拖动 GUI 界面就会卡死,发生未响应的情况,直到后端代码运行完成后,GUI 界面才会恢复响应。为什么会出现这种情况呢?这就是由于发生了线程的堵塞。比如只有一条道路,前端要走,后端也要走。当后端代码顺利运行后,道路就被堵上了。这时操作前端,由于路被堵上,前端 GUI 界面出现卡死、未响应。直到后端代码运行结束,路通了,前端才可以回应我们的操作,如鼠标点击、拖拽等。 一个正常的程序在后台运行时,人员也是可以操作图形界面的,甚至再开启一个后台,正常来说不会出现卡死的情况(排除内存泄漏、内存占用过高等情况)。

那么要怎样才能实现呢? 使用多线程或者多进程,由于 Python 语言现阶段存在 GIL 的情况(没准以后就没有了),使用多线程只对 IO 密集工作有较好的效果。所以我们这里使用多进程:开启两个进程,相当于有了两条路,GUI 走一条,后端程序走另一条。  开启多进程以下的源代码会在重要位置标注注释,如 #<<注释1>>。并且下边会有详细说明。

只需要在 makeGUI.py 文件中添加修改几行代码即可实现。代码如下:# -*- coding:utf-8 -*-import Tkinter as tkimport tkFileDialogimport giscodefrom multiprocessing import Process #<<注释1>>class MyGUI(object):def __init__(self):self.root = tk.Tk()self.root.geometry("450x600+800+200") #设置窗口大小、位置self.root.title("GIS") #设置程序名称self.var = tk.StringVar()# run functionself.create_widget()self.create_run_button()self.root.mainloop() # 执行循环def create_widget(self):self.frame1 = tk.Frame(self.root, relief="raised", bd=3)self.frame1.pack(fill="x")self.entry = tk.Entry(self.frame1)self.entry.config(textvariable=self.var) #<<注释2>>self.entry.pack(side="left",expand=True,fill="x", pady=8, padx=10)self.but = tk.Button(self.frame1, text=u"输入线要素",relief="groove", width=10)self.but.config(command=self.open_dialog)self.but.pack(side="right", pady=8)def open_dialog(self):varrr = tkFileDialog.askopenfilename()self.var.set(varrr)def create_run_button(self):# 生成下方的“运行”按钮self.bottom_frame = tk.Frame(self.root,relief="raised",bd=3)self.bottom_frame.pack(side="bottom",fill="x",anchor="s")self.ok_button =tk.Button(self.bottom_frame,text=u"运行",relief="groove", width=10)self.ok_button.pack(side="right", pady=8)self.ok_button.config(command=self.run_multiprocessing) #<<注释2>># def run(self):# giscode.main(self.var.get())def run_multiprocessing(self): #<<注释3>>p = Process(target=giscode.main,args=(self.var.get(),))p.start()print "PID:",p.pidif __name__ == '__main__':MyGUI()<<注释1>>:multiprocessing 是 Python 自带的多进程管理库。其中的 Process 模块用于创建一个新的进程对象。 <<注释2>>:将点击按钮触发的  run 方法改成了一个新建的 run_multiprocessing 方法。该方法是新创建的,作用是创建一个新进程来运行后端的代码。 <<注释3>>:创建一个方法便于按钮点击触发。Process 是一个类,用于创建一个新的进程对象,常用的参数是 target 和 args 参数。target:接收名字。 target 参数接收函数、方法或者类的名字,不加括号。在使用 Process 类中 start 后,新创建的进程就会执行  target 接收的参数。args:接收元组参数。 既然 target 接收函数、方法或者类,那么如果这些函数、方法或者类也存在参数怎么办呢?所以这里使用 args  接收获得参数。接收形式为参数组成的元组:args=(var1, var2)。Note: 接收单个参数要加逗号,如:args=(var1,) 加一个逗号避免产生歧义,否则会导致字符串被拆分成元组,比如 "use" 被拆分成三部分 ("u","s","e")执行程序

使用最新修改后的 makeGUI.py 文件即可。 结束语

第五章的源代码和演示用矢量文件下载地址:链接:https://pan.baidu.com/s/1JMo5h16DihUjpdGrDCEOKg  提取码:pu9h  分享GIS,不止于Python。荟GIS精粹,关注我,带你飞!我叫 GIS荟欢迎交流

(0)

相关推荐