日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

用Python創(chuàng)建你第一個(gè)GIS程序[5]:多進(jìn)程解決線程堵塞

 GIS薈 2021-09-19

前言:在上一章中,我們將前后端連接起來(lái),算是真正把程序給創(chuàng)建了出來(lái)。但是存在一個(gè)問(wèn)題:當(dāng)你點(diǎn)擊“運(yùn)行”按鈕運(yùn)行程序后,再用鼠標(biāo)點(diǎn)擊拖動(dòng) GUI 界面就會(huì)卡死...




線程堵塞

當(dāng)點(diǎn)擊“運(yùn)行”按鈕運(yùn)行程序后,再用鼠標(biāo)點(diǎn)擊拖動(dòng) GUI 界面就會(huì)卡死,發(fā)生未響應(yīng)的情況,直到后端代碼運(yùn)行完成后,GUI 界面才會(huì)恢復(fù)響應(yīng)。
為什么會(huì)出現(xiàn)這種情況呢?
這就是由于發(fā)生了線程的堵塞。
比如只有一條道路,前端要走,后端也要走。當(dāng)后端代碼順利運(yùn)行后,道路就被堵上了。
這時(shí)操作前端,由于路被堵上,前端 GUI 界面出現(xiàn)卡死、未響應(yīng)。
直到后端代碼運(yùn)行結(jié)束,路通了,前端才可以回應(yīng)我們的操作,如鼠標(biāo)點(diǎn)擊、拖拽等。
 
一個(gè)正常的程序在后臺(tái)運(yùn)行時(shí),人員也是可以操作圖形界面的,甚至再開(kāi)啟一個(gè)后臺(tái),正常來(lái)說(shuō)不會(huì)出現(xiàn)卡死的情況(排除內(nèi)存泄漏、內(nèi)存占用過(guò)高等情況)。

 
那么要怎樣才能實(shí)現(xiàn)呢?
 
使用多線程或者多進(jìn)程,由于 Python 語(yǔ)言現(xiàn)階段存在 GIL 的情況(沒(méi)準(zhǔn)以后就沒(méi)有了),使用多線程只對(duì) IO 密集工作有較好的效果。
所以我們這里使用多進(jìn)程:開(kāi)啟兩個(gè)進(jìn)程,相當(dāng)于有了兩條路,GUI 走一條,后端程序走另一條。
 
 

開(kāi)啟多進(jìn)程

以下的源代碼會(huì)在重要位置標(biāo)注注釋?zhuān)?#<<注釋1>>。并且下邊會(huì)有詳細(xì)說(shuō)明。

只需要在 makeGUI.py 文件中添加修改幾行代碼即可實(shí)現(xiàn)。
代碼如下:

# -*- coding:utf-8 -*-

import Tkinter as tk

import tkFileDialog

import giscode

from multiprocessing import Process #<<注釋1>>

class MyGUI(object):

def __init__(self):

self.root = tk.Tk()

self.root.geometry("450x600+800+200") #設(shè)置窗口大小、位置

self.root.title("GIS") #設(shè)置程序名稱(chēng)

self.var = tk.StringVar()

# run function

self.create_widget()

self.create_run_button()

self.root.mainloop() # 執(zhí)行循環(huán)

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

# 生成下方的“運(yùn)行”按鈕

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"運(yùn)行",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.pid

if __name__ == '__main__':

MyGUI()

<<注釋1>>:multiprocessing 是 Python 自帶的多進(jìn)程管理庫(kù)。其中的 Process 模塊用于創(chuàng)建一個(gè)新的進(jìn)程對(duì)象。
 
<<注釋2>>:將點(diǎn)擊按鈕觸發(fā)的  run 方法改成了一個(gè)新建的 run_multiprocessing 方法。該方法是新創(chuàng)建的,作用是創(chuàng)建一個(gè)新進(jìn)程來(lái)運(yùn)行后端的代碼。
 
<<注釋3>>:創(chuàng)建一個(gè)方法便于按鈕點(diǎn)擊觸發(fā)。Process 是一個(gè)類(lèi),用于創(chuàng)建一個(gè)新的進(jìn)程對(duì)象,常用的參數(shù)是 target 和 args 參數(shù)。
target:接收名字。
?target 參數(shù)接收函數(shù)、方法或者類(lèi)的名字,不加括號(hào)。在使用 Process 類(lèi)中 start 后,新創(chuàng)建的進(jìn)程就會(huì)執(zhí)行 ?target 接收的參數(shù)。
args:接收元組參數(shù)。
?既然 target 接收函數(shù)、方法或者類(lèi),那么如果這些函數(shù)、方法或者類(lèi)也存在參數(shù)怎么辦呢?所以這里使用 args ?接收獲得參數(shù)。接收形式為參數(shù)組成的元組:args=(var1, var2)。

Note: 接收單個(gè)參數(shù)要加逗號(hào),如:args=(var1,) 加一個(gè)逗號(hào)避免產(chǎn)生歧義,否則會(huì)導(dǎo)致字符串被拆分成元組,比如 "use" 被拆分成三部分 ("u","s","e")
 

執(zhí)行程序

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

結(jié)束語(yǔ)

第五章的源代碼和演示用矢量文件下載地址:
鏈接:https://pan.baidu.com/s/1JMo5h16DihUjpdGrDCEOKg  
提取碼:pu9h  

分享GIS,不止于Python。
薈GIS精粹,關(guān)注我,帶你飛!
我叫 GIS薈

歡迎交流

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多