【问题标题】:callback given to call_soon or call_soon_threadsafe is never called永远不会调用给 call_soon 或 call_soon_threadsafe 的回调
【发布时间】:2019-07-08 05:32:29
【问题描述】:

我想每隔 N 秒在主线程循环上调用一个函数。

为此,使用 _timer_handler() 函数初始化 Threading.Timer。 该函数在 Timer 线程上下文中调用,我尝试在主线程循环中调用 _refresh_token() 但从未调用过。

# coding: utf-8
import asyncio
import datetime
import time
import threading

def thread_msg(msg):
    print("{} - Current Thread is {} | {} |".format(datetime.datetime.now(), threading.current_thread().ident, threading.current_thread().name), msg)

class My_Session():

    def __init__(self, delay=30):
        self._timer = None
        self._delay = delay
        self._loop = asyncio.get_event_loop()

    def start(self):
        thread_msg("Start session")
        self._init_timer()

    def stop(self):
        if self._timer:
            self._timer.cancel()
        thread_msg("Stop session")

    def _init_timer(self):
        self._timer = threading.Timer(self._delay, self._timer_handler)
        print("Set timer to {} seconds to refresh token".format(self._delay))
        self._timer.start()

    def _timer_handler(self):
        try:
            thread_msg("Time out, call self._refresh_token")
            self._loop.call_soon_threadsafe(self._refresh_token)
            thread_msg("call self._refresh_token done")
        except Exception as e:
            thread_msg("Exception in _timer_handler: {}".format(e))

    def _refresh_token(self):
        thread_msg("_refresh_token is called properly,\n   reinitialize the timer...")
        self._init_timer()

if __name__ == '__main__':
    thread_msg("Start script")
    session = My_Session(5)
    session.start()
    try:
        while True:
            thread_msg("loop")
            time.sleep(1)
    except KeyboardInterrupt:
        session.stop()

输出是:

2019-06-24 20:21:29.776809 - Current Thread is 10220 | MainThread | Start script
2019-06-24 20:21:29.777906 - Current Thread is 10220 | MainThread | Start session
Set timer to 5 seconds to refresh token
2019-06-24 20:21:29.778310 - Current Thread is 10220 | MainThread | loop
2019-06-24 20:21:30.787545 - Current Thread is 10220 | MainThread | loop
2019-06-24 20:21:31.791333 - Current Thread is 10220 | MainThread | loop
2019-06-24 20:21:32.794627 - Current Thread is 10220 | MainThread | loop
2019-06-24 20:21:33.806744 - Current Thread is 10220 | MainThread | loop
2019-06-24 20:21:34.790288 - Current Thread is 17148 | Thread-1 | Time out, call self._refresh_token
2019-06-24 20:21:34.790573 - Current Thread is 17148 | Thread-1 | call self._refresh_token done
2019-06-24 20:21:34.820744 - Current Thread is 10220 | MainThread | loop
2019-06-24 20:21:35.822738 - Current Thread is 10220 | MainThread | loop
2019-06-24 20:21:36.830907 - Current Thread is 10220 | MainThread | loop
2019-06-24 20:21:37.833233 - Current Thread is 10220 | MainThread | loop

【问题讨论】:

    标签: python-3.x python-multithreading asynccallback


    【解决方案1】:

    解决方案: 替换 time.sleep(1) 使用 asyncio.get_event_loop().run_until_complete(asyncio.sleep(1))

    那么,输出是:

    2019-07-07 23:25:26.128351 - Current Thread is 49704 | MainThread | Start script
    2019-07-07 23:25:26.129315 - Current Thread is 49704 | MainThread | Start session
    Set timer to 5 seconds to refresh token
    2019-07-07 23:25:26.130314 - Current Thread is 49704 | MainThread | loop <_WindowsSelectorEventLoop running=False closed=False debug=False>
    2019-07-07 23:25:28.131111 - Current Thread is 49704 | MainThread | loop <_WindowsSelectorEventLoop running=False closed=False debug=False>
    2019-07-07 23:25:30.131815 - Current Thread is 49704 | MainThread | loop <_WindowsSelectorEventLoop running=False closed=False debug=False>
    2019-07-07 23:25:31.130414 - Current Thread is 17000 | Thread-1 | Time out, call self._refresh_token
    2019-07-07 23:25:31.130414 - Current Thread is 17000 | Thread-1 | call self._refresh_token done2019-07-07 23:25:31.130414 - Current Thread is 49704 | MainThread    
    _refresh_token is called properly,
    reinitialize the timer...
    Set timer to 5 seconds to refresh token
    2019-07-07 23:25:32.132879 - Current Thread is 49704 | MainThread | loop <_WindowsSelectorEventLoop running=False closed=False debug=False>
    2019-07-07 23:25:34.134277 - Current Thread is 49704 | MainThread | loop <_WindowsSelectorEventLoop running=False closed=False debug=False>
    2019-07-07 23:25:36.131731 - Current Thread is 19988 | Thread-2 | Time out, call self._refresh_token
    2019-07-07 23:25:36.132455 - Current Thread is 19988 | Thread-2 | call self._refresh_token done
    2019-07-07 23:25:36.132455 - Current Thread is 49704 | MainThread | _refresh_token is called properly,
    reinitialize the timer...
    Set timer to 5 seconds to refresh token
    2019-07-07 23:25:36.133478 - Current Thread is 49704 | MainThread | loop <_WindowsSelectorEventLoop running=False closed=False debug=False>
    2019-07-07 23:25:38.134883 - Current Thread is 49704 | MainThread | loop <_WindowsSelectorEventLoop running=False closed=False debug=False>
    2019-07-07 23:25:40.135312 - Current Thread is 49704 | MainThread | loop <_WindowsSelectorEventLoop running=False closed=False debug=False>
    2019-07-07 23:25:41.133663 - Current Thread is 25112 | Thread-3 | Time out, call self._refresh_token
    2019-07-07 23:25:41.133663 - Current Thread is 25112 | Thread-3 |2019-07-07     
    23:25:41.133663 - Current Thread is 49704 | MainThread |  call self._refresh_token done
    _refresh_token is called properly,
    reinitialize the timer...
    Set timer to 5 seconds to refresh token
    ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-18
      • 1970-01-01
      • 1970-01-01
      • 2015-07-28
      • 2013-11-23
      • 2017-12-06
      • 2017-07-26
      • 1970-01-01
      相关资源
      最近更新 更多