最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python應(yīng)用開(kāi)發(fā)頻繁假死的問(wèn)題分析及解決

 更新時(shí)間:2024年08月02日 09:01:23   作者:設(shè)計(jì)筆記  
最近在開(kāi)發(fā)一款自動(dòng)化的應(yīng)用,但是,在測(cè)試時(shí),卻發(fā)現(xiàn)了問(wèn)題,當(dāng)我點(diǎn)擊暫停任務(wù)后,此時(shí)子線程被阻塞,如果我這個(gè)時(shí)候點(diǎn)擊停止,那么就會(huì)任務(wù)結(jié)束,之后,如果我再點(diǎn)擊開(kāi)始運(yùn)行,整個(gè)應(yīng)用就會(huì)卡死,所以本文介紹了Python應(yīng)用開(kāi)發(fā)頻繁假死的問(wèn)題分析及解決,需要的朋友可以參考下

問(wèn)題背景

最近在開(kāi)發(fā)一款自動(dòng)化的應(yīng)用,其中有一個(gè)自動(dòng)化任務(wù)會(huì)由下面這三個(gè)按鈕控制:

邏輯也很簡(jiǎn)單,我大概畫(huà)下圖就是這樣的:

但是,在測(cè)試時(shí),卻發(fā)現(xiàn)了問(wèn)題:

當(dāng)我點(diǎn)擊暫停任務(wù)后,此時(shí)子線程被阻塞。如果我這個(gè)時(shí)候點(diǎn)擊停止,那么就會(huì)任務(wù)結(jié)束。

之后,如果我再點(diǎn)擊開(kāi)始運(yùn)行,整個(gè)應(yīng)用就會(huì)卡死,非常離譜。

以下是簡(jiǎn)化后的代碼:

 import threading
 import time
 from sample_singleton import singleton
 ?
 @singleton
 class TestThreadingEvent:
     def __init__(self):
         self._stop_event = threading.Event()
         self._pause_event = threading.Event()
         self._thread = None
 ?
     def set_stop(self):
         self._stop_event.set()
 ?
     def set_pause(self):
         self._pause_event.set()
 ?
     def start(self):
         print("任務(wù)開(kāi)始")
         self._stop_event.clear()
         self._pause_event.set()
         print("開(kāi)始執(zhí)行")
         self._thread = threading.Thread(target=self._run)
         self._thread.start()
 ?
     def _run(self):
         count = 0
         while True:
             if self._stop_event.is_set():
                 print("任務(wù)被成功停止")
                 return
             print(f"是否需要暫停:{not self._pause_event.is_set()}")
             self._pause_event.wait()
             # 執(zhí)行任務(wù)
             print(f"do something: {count}")
             time.sleep(1)
             count += 1
 ?
     def pause(self):
         print("點(diǎn)擊了暫停")
         self._pause_event.clear()
         time.sleep(2)
 ?
     def stop(self):
         print("點(diǎn)擊了停止")
         self._stop_event.set()
         print("成功停止")
         if self._thread is not None:
             self._thread.join()  # 確保線程終止
 ?
 ?
 print("我點(diǎn)擊了開(kāi)始")
 singletonA = TestThreadingEvent()
 singletonA.start()
 singletonA.pause()
 print("我點(diǎn)擊了停止")
 singletonA.stop()
 print("我再次點(diǎn)擊了開(kāi)始")
 singletonA.start()

按照代碼邏輯,我期待的結(jié)果是點(diǎn)擊停止后,再次點(diǎn)擊開(kāi)始就可以開(kāi)始重新運(yùn)行,但是,雖然第一次顯示停止了,可如果想再次開(kāi)始,程序就會(huì)卡住不動(dòng)了,下面為測(cè)試時(shí)輸出的結(jié)果:

 我點(diǎn)擊了開(kāi)始
 任務(wù)開(kāi)始
 開(kāi)始執(zhí)行
 是否需要暫停:False
 do something: 0
 我點(diǎn)擊了暫停
 是否需要暫停:True
 我點(diǎn)擊了停止
 成功停止
 # 然后在這里卡死

昨天下午一直在代碼中斷點(diǎn)找原因,搞了半天,都沒(méi)能解決,下班前我甚至都在懷疑是不是 Python 代碼的問(wèn)題,想去看看源碼找原因了。

找出原因

不過(guò)簡(jiǎn)化代碼,確實(shí)比較有效,當(dāng)我把整個(gè)流程簡(jiǎn)化成上面的代碼,就比較方便找出問(wèn)題出在哪里了。

是因?yàn)椋?dāng)我點(diǎn)擊“暫停”后,子線程進(jìn)入阻塞狀態(tài)。當(dāng)執(zhí)行“停止”操作時(shí),使用了 self._thread.join(),這會(huì)導(dǎo)致主線程阻塞,直到子線程 self._thread 完成。然而,如果子線程因阻塞狀態(tài)無(wú)法完成,就會(huì)導(dǎo)致主線程永久等待,結(jié)果是主線程卡死。

后面我看了下我們實(shí)際開(kāi)發(fā)的應(yīng)用代碼,問(wèn)題要更復(fù)雜點(diǎn),但說(shuō)到底,都是線程阻塞狀態(tài)沒(méi)有得到正確處理,導(dǎo)致的卡死。

解決辦法

由于主線程卡死是子線程的阻塞狀態(tài)造成的,可以通過(guò)以下兩種方法解決:

  • 處理子線程阻塞:引入超時(shí)控制,確保子線程在合理時(shí)間內(nèi)完成任務(wù),并在必要時(shí)修改子線程的阻塞狀態(tài),以避免主線程長(zhǎng)時(shí)間等待。
  • 銷(xiāo)毀子線程:如果子線程在完成任務(wù)后不再需要重復(fù)使用,可以考慮在結(jié)束時(shí)直接銷(xiāo)毀該線程,以避免阻塞主線程。

這兩種方法可以有效避免主線程因子線程阻塞而卡死的問(wèn)題。

以上就是Python應(yīng)用開(kāi)發(fā)頻繁假死的問(wèn)題分析及解決的詳細(xì)內(nèi)容,更多關(guān)于Python應(yīng)用開(kāi)發(fā)假死的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

图片| 隆昌县| 辽中县| 铜山县| 比如县| 赤城县| 林州市| 永清县| 太原市| 昌邑市| 凤庆县| 叶城县| 天镇县| 霍山县| 高陵县| 黔南| 云浮市| 军事| 重庆市| 通辽市| 永定县| 曲松县| 长顺县| 岑巩县| 永登县| 图们市| 石嘴山市| 张掖市| 元江| 平原县| 双辽市| 潼关县| 吴川市| 金门县| 民乐县| 玉环县| 澎湖县| 柳河县| 东平县| 新蔡县| 保亭|