背景
利用多線程實現一個開關功能,需要對產生的線程進行管理(例如:開啟,暫停,關閉等操作)。
實現代碼
任務腳本:
#!/usr/bin/python3
# _*_ coding: utf-8 _*_
"""
@Software: PyCharm
@File: ac_job.py
@Author: 高留柱
@E-mail: liuzhu.gao@foxmail.com
@Time: 2020/9/19 10:30 上午
@Notes: 用於開啟線程,執行ac_work中的任務
"""
import threading
from utils.hfac_lib import hfac_work
class Job(threading.Thread):
def __init__(self, *args, **kwargs):
super(Job, self).__init__(*args, **kwargs)
self.__flag = threading.Event() # 用於暫停線程的標識
self.__flag.set() # 設置為True
self.__running = threading.Event() # 用於停止線程的標識
self.__running.set() # 將running設置為True
def run(self):
while self.__running.isSet():
self.__flag.wait() # 為True時立即返回, 為False時阻塞直到內部的標識位為True后返回
try:
# 任務
hfac_work.start_ac()
except Exception as e:
# 如果任務失敗,自動結束該線程,外層可用方法判斷線程是否存活,從而判斷任務是否失敗。
# return 方法在線程中不能使用
self.stop()
print(e)
def pause(self):
self.__flag.clear() # 設置為False, 讓線程阻塞
def resume(self):
self.__flag.set() # 設置為True, 讓線程停止阻塞
def stop(self):
self.__flag.set() # 將線程從暫停狀態恢復, 如何已經暫停的話
self.__running.clear() # 設置為False
調用腳本:
方法:
- job.start() 啟動線程
- job.stop() 停止線程
- job.pause() 暫停線程
- job.resume() 恢復線程
- job.is_alive() 判斷線程是否存活
無論是暫停還是停止, 都不是瞬時的, 必須等待run函數內部的運行到達標志位判斷時才有效. 也就是說操作會滯后一次.
因此,在主進程中停止線程的任務,在使用is_alive()方法之前最好加上個time.sleep(),防止線程滯后,導致is_alive()方法失敗
def post(self, request, *args, **kwargs):
"""
開始和停止測試(控制電源硬件)
:param request:
:param args:
:param kwargs:
:return:
"""
global job, is_start
is_run = request.POST.get("is_run")
if not job:
job = ac_job.Job()
if is_run == "1":
if not is_start:
job.start()
# 此處time.sleep一會兒,如果線程中出現異常會調用self.stop,延遲一會兒,方便線程終止后判斷是否存活線程
# 如果不延遲一會兒,主進程檢測是否存活的時候,線程還沒死掉
time.sleep(3)
if not job.is_alive():
return APIResponse(1, "程序開始失敗,請檢查電源的com口是否異常!", result="")
is_start = True
return APIResponse(msg="開始測試!", result="")
return APIResponse(1, "程序已經在測試中,需要先停止!", result="")
else:
if is_start:
job.stop()
job = None
is_start = False
return APIResponse(msg="測試已停止!", result="")
return APIResponse(1, "程序沒有在測試中,無法停止!", result="")