检查线程是否已在 MicroPython 中启动
Checking to see if a thread has started in MicroPython
我只是在 LEGO EV3 单元上尝试一些 MicroPython 脚本,我正在努力寻找任何 documentation/examples 告诉我如何检查线程是否 运行。
def newMethod():
print("new method")
t1 = threading.Thread(target=newMethod)
while True:
...
if t1.is_alive() is False:
t1.start()
现在可以工作了,除了测试 t1 是否已经启动。但它是Python2.7。值得庆幸的是,除了 is_alive?我收到一个错误。
Traceback (most recent call last):
File "./micro.py", line 79, in <module>
File "./micro.py", line 73, in <module>
AttributeError: 'Thread' object has no attribute 'is_alive'
我需要手动跟踪吗?或者是否有像 python 2.7
这样的内置方法
is_alive
目前还没有为任何支持线程的端口实现(在官方存储库中,不知道其他的)。所以你的选择是:
- 手动追踪
- 在您的代码中使用不同的逻辑,因此您不需要它
- create a feature request
- 自己为你使用的端口实现它(如果你知道 C 这可能相对容易,因为线程实现通常有一个 built-in 报告它们状态的方法)
对于最后一个案例,我很好奇并想到了这个,对于 unix 端口,因为我没有 Lego 可以玩,它将 is_alive
添加到 _thread
模块。从那时起,将它放入您的 Threading
class 应该相当容易。请注意,这只是为了让您了解它需要什么,并且是未经测试的概念证明,YMMV。补丁:
--- a/ports/unix/mpthreadport.c
+++ b/ports/unix/mpthreadport.c
@@ -174,7 +174,20 @@ void mp_thread_start(void) {
pthread_mutex_unlock(&thread_mutex);
}
-void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) {
+int mp_thread_is_alive(void* id) {
+ int ready = 0;
+ pthread_mutex_lock(&thread_mutex);
+ for (thread_t *th = thread; th != NULL; th = th->next) {
+ if (th->id == (pthread_t)id && th->ready) {
+ ready = 1;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&thread_mutex);
+ return ready;
+}
+
+void* mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) {
// default stack size is 8k machine-words
if (*stack_size == 0) {
*stack_size = 8192 * BYTES_PER_WORD;
@@ -225,7 +238,7 @@ void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) {
pthread_mutex_unlock(&thread_mutex);
- return;
+ return (void*) th->id;
er:
mp_raise_OSError(ret);
diff --git a/py/modthread.c b/py/modthread.c
index 91237a7..246dd5c 100644
--- a/py/modthread.c
+++ b/py/modthread.c
@@ -264,9 +264,7 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args)
th_args->fun = args[0];
// spawn the thread!
- mp_thread_create(thread_entry, th_args, &th_args->stack_size);
-
- return mp_const_none;
+ return mp_obj_new_int_from_uint((uintptr_t)mp_thread_create(thread_entry, th_args, &th_args->stack_size));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_start_new_thread_obj, 2, 3, mod_thread_start_new_thread);
@@ -275,6 +273,11 @@ STATIC mp_obj_t mod_thread_exit(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_exit_obj, mod_thread_exit);
+STATIC mp_obj_t mod_thread_is_alive(mp_obj_t id) {
+ return mp_obj_new_bool(mp_thread_is_alive((void*) mp_obj_get_int(id)));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_thread_is_alive_obj, mod_thread_is_alive);
+
STATIC mp_obj_t mod_thread_allocate_lock(void) {
return MP_OBJ_FROM_PTR(mp_obj_new_thread_lock());
}
@@ -287,6 +290,7 @@ STATIC const mp_rom_map_elem_t mp_module_thread_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_stack_size), MP_ROM_PTR(&mod_thread_stack_size_obj) },
{ MP_ROM_QSTR(MP_QSTR_start_new_thread), MP_ROM_PTR(&mod_thread_start_new_thread_obj) },
{ MP_ROM_QSTR(MP_QSTR_exit), MP_ROM_PTR(&mod_thread_exit_obj) },
+ { MP_ROM_QSTR(MP_QSTR_is_alive), MP_ROM_PTR(&mod_thread_is_alive_obj) },
{ MP_ROM_QSTR(MP_QSTR_allocate_lock), MP_ROM_PTR(&mod_thread_allocate_lock_obj) },
};
diff --git a/py/mpthread.h b/py/mpthread.h
index 602df83..46f1a3a 100644
--- a/py/mpthread.h
+++ b/py/mpthread.h
@@ -40,7 +40,8 @@ struct _mp_state_thread_t;
struct _mp_state_thread_t *mp_thread_get_state(void);
void mp_thread_set_state(void *state);
-void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size);
+void* mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size);
+int mp_thread_is_alive(void*);
启用如下代码:
import _thread
import utime
def Entry():
utime.sleep_ms(1)
t = _thread.start_new_thread(Entry, ())
for i in range(10):
print('thread alive', _thread.is_alive(t))
打印几次 True,然后打印 False。
我只是在 LEGO EV3 单元上尝试一些 MicroPython 脚本,我正在努力寻找任何 documentation/examples 告诉我如何检查线程是否 运行。
def newMethod():
print("new method")
t1 = threading.Thread(target=newMethod)
while True:
...
if t1.is_alive() is False:
t1.start()
现在可以工作了,除了测试 t1 是否已经启动。但它是Python2.7。值得庆幸的是,除了 is_alive?我收到一个错误。
Traceback (most recent call last):
File "./micro.py", line 79, in <module>
File "./micro.py", line 73, in <module>
AttributeError: 'Thread' object has no attribute 'is_alive'
我需要手动跟踪吗?或者是否有像 python 2.7
这样的内置方法is_alive
目前还没有为任何支持线程的端口实现(在官方存储库中,不知道其他的)。所以你的选择是:
- 手动追踪
- 在您的代码中使用不同的逻辑,因此您不需要它
- create a feature request
- 自己为你使用的端口实现它(如果你知道 C 这可能相对容易,因为线程实现通常有一个 built-in 报告它们状态的方法)
对于最后一个案例,我很好奇并想到了这个,对于 unix 端口,因为我没有 Lego 可以玩,它将 is_alive
添加到 _thread
模块。从那时起,将它放入您的 Threading
class 应该相当容易。请注意,这只是为了让您了解它需要什么,并且是未经测试的概念证明,YMMV。补丁:
--- a/ports/unix/mpthreadport.c
+++ b/ports/unix/mpthreadport.c
@@ -174,7 +174,20 @@ void mp_thread_start(void) {
pthread_mutex_unlock(&thread_mutex);
}
-void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) {
+int mp_thread_is_alive(void* id) {
+ int ready = 0;
+ pthread_mutex_lock(&thread_mutex);
+ for (thread_t *th = thread; th != NULL; th = th->next) {
+ if (th->id == (pthread_t)id && th->ready) {
+ ready = 1;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&thread_mutex);
+ return ready;
+}
+
+void* mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) {
// default stack size is 8k machine-words
if (*stack_size == 0) {
*stack_size = 8192 * BYTES_PER_WORD;
@@ -225,7 +238,7 @@ void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) {
pthread_mutex_unlock(&thread_mutex);
- return;
+ return (void*) th->id;
er:
mp_raise_OSError(ret);
diff --git a/py/modthread.c b/py/modthread.c
index 91237a7..246dd5c 100644
--- a/py/modthread.c
+++ b/py/modthread.c
@@ -264,9 +264,7 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args)
th_args->fun = args[0];
// spawn the thread!
- mp_thread_create(thread_entry, th_args, &th_args->stack_size);
-
- return mp_const_none;
+ return mp_obj_new_int_from_uint((uintptr_t)mp_thread_create(thread_entry, th_args, &th_args->stack_size));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_start_new_thread_obj, 2, 3, mod_thread_start_new_thread);
@@ -275,6 +273,11 @@ STATIC mp_obj_t mod_thread_exit(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_exit_obj, mod_thread_exit);
+STATIC mp_obj_t mod_thread_is_alive(mp_obj_t id) {
+ return mp_obj_new_bool(mp_thread_is_alive((void*) mp_obj_get_int(id)));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_thread_is_alive_obj, mod_thread_is_alive);
+
STATIC mp_obj_t mod_thread_allocate_lock(void) {
return MP_OBJ_FROM_PTR(mp_obj_new_thread_lock());
}
@@ -287,6 +290,7 @@ STATIC const mp_rom_map_elem_t mp_module_thread_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_stack_size), MP_ROM_PTR(&mod_thread_stack_size_obj) },
{ MP_ROM_QSTR(MP_QSTR_start_new_thread), MP_ROM_PTR(&mod_thread_start_new_thread_obj) },
{ MP_ROM_QSTR(MP_QSTR_exit), MP_ROM_PTR(&mod_thread_exit_obj) },
+ { MP_ROM_QSTR(MP_QSTR_is_alive), MP_ROM_PTR(&mod_thread_is_alive_obj) },
{ MP_ROM_QSTR(MP_QSTR_allocate_lock), MP_ROM_PTR(&mod_thread_allocate_lock_obj) },
};
diff --git a/py/mpthread.h b/py/mpthread.h
index 602df83..46f1a3a 100644
--- a/py/mpthread.h
+++ b/py/mpthread.h
@@ -40,7 +40,8 @@ struct _mp_state_thread_t;
struct _mp_state_thread_t *mp_thread_get_state(void);
void mp_thread_set_state(void *state);
-void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size);
+void* mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size);
+int mp_thread_is_alive(void*);
启用如下代码:
import _thread
import utime
def Entry():
utime.sleep_ms(1)
t = _thread.start_new_thread(Entry, ())
for i in range(10):
print('thread alive', _thread.is_alive(t))
打印几次 True,然后打印 False。