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

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

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

問題背景

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

邏輯也很簡單,我大概畫下圖就是這樣的:

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

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

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

以下是簡化后的代碼:

 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ù)開始")
         self._stop_event.clear()
         self._pause_event.set()
         print("開始執(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)擊了開始")
 singletonA = TestThreadingEvent()
 singletonA.start()
 singletonA.pause()
 print("我點(diǎn)擊了停止")
 singletonA.stop()
 print("我再次點(diǎn)擊了開始")
 singletonA.start()

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

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

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

找出原因

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

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

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

解決辦法

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

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

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

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

相關(guān)文章

最新評論

庄河市| 安泽县| 东至县| 长丰县| 康马县| 宜兰县| 汪清县| 嘉鱼县| 雅安市| 毕节市| 若尔盖县| 贡山| 桓仁| 海晏县| 平湖市| 宜城市| 湖北省| 平乡县| 鄯善县| 连平县| 谷城县| 乌拉特前旗| 沁水县| 大理市| 兰溪市| 宾川县| 平和县| 庄河市| 汶川县| 陈巴尔虎旗| 志丹县| 光泽县| 万州区| 西乌珠穆沁旗| 兴山县| 怀集县| 丰台区| 阜阳市| 湛江市| 安西县| 万年县|