2025-09-22 19:10:58 +08:00
|
|
|
|
import ctypes
|
2025-09-17 22:23:57 +08:00
|
|
|
|
import threading
|
2025-09-19 19:39:32 +08:00
|
|
|
|
from typing import Dict, Tuple, List
|
2025-09-22 19:10:58 +08:00
|
|
|
|
|
2025-08-06 22:11:33 +08:00
|
|
|
|
from Utils.LogManager import LogManager
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-09-22 19:10:58 +08:00
|
|
|
|
def _async_raise(tid: int, exc_type=KeyboardInterrupt):
|
|
|
|
|
|
"""向指定线程抛异常,强制跳出"""
|
|
|
|
|
|
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), ctypes.py_object(exc_type))
|
|
|
|
|
|
if res == 0:
|
|
|
|
|
|
raise ValueError("线程不存在")
|
|
|
|
|
|
elif res > 1:
|
|
|
|
|
|
ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), 0)
|
|
|
|
|
|
|
2025-09-17 22:23:57 +08:00
|
|
|
|
class ThreadManager:
|
2025-09-18 20:09:52 +08:00
|
|
|
|
_tasks: Dict[str, Dict] = {}
|
2025-09-17 22:23:57 +08:00
|
|
|
|
_lock = threading.Lock()
|
2025-08-06 22:11:33 +08:00
|
|
|
|
|
|
|
|
|
|
@classmethod
|
2025-09-18 20:09:52 +08:00
|
|
|
|
def add(cls, udid: str, thread: threading.Thread, event: threading.Event) -> Tuple[int, str]:
|
2025-09-22 19:10:58 +08:00
|
|
|
|
LogManager.method_info(f"准备创建任务:{udid}", "task")
|
2025-09-18 20:09:52 +08:00
|
|
|
|
with cls._lock:
|
2025-09-22 19:10:58 +08:00
|
|
|
|
# 判断当前设备是否有任务
|
|
|
|
|
|
if cls._tasks.get(udid, None) is not None:
|
|
|
|
|
|
return 1001, "当前设备已存在任务"
|
|
|
|
|
|
thread.start()
|
|
|
|
|
|
print(thread.ident)
|
2025-09-18 20:09:52 +08:00
|
|
|
|
|
|
|
|
|
|
cls._tasks[udid] = {
|
2025-09-22 19:10:58 +08:00
|
|
|
|
"id": thread.ident,
|
2025-09-18 20:09:52 +08:00
|
|
|
|
"thread": thread,
|
2025-09-22 19:10:58 +08:00
|
|
|
|
"event": event
|
2025-09-18 20:09:52 +08:00
|
|
|
|
}
|
2025-09-22 19:10:58 +08:00
|
|
|
|
return 200, "创建成功"
|
2025-08-06 22:11:33 +08:00
|
|
|
|
|
|
|
|
|
|
@classmethod
|
2025-09-18 20:09:52 +08:00
|
|
|
|
def stop(cls, udid: str) -> Tuple[int, str]:
|
2025-09-22 19:10:58 +08:00
|
|
|
|
try:
|
|
|
|
|
|
print(cls._tasks)
|
|
|
|
|
|
obj = cls._tasks.get(udid, None)
|
|
|
|
|
|
obj["event"].set()
|
|
|
|
|
|
r = cls._kill_thread(obj.get("id"))
|
|
|
|
|
|
if r:
|
|
|
|
|
|
cls._tasks.pop(udid, None)
|
|
|
|
|
|
else:
|
|
|
|
|
|
print("好像有问题")
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(e)
|
|
|
|
|
|
return 200, "操作成功"
|
2025-09-17 22:23:57 +08:00
|
|
|
|
|
2025-09-19 19:39:32 +08:00
|
|
|
|
@classmethod
|
2025-09-22 19:10:58 +08:00
|
|
|
|
def batch_stop(cls, ids: List[str]) -> Tuple[int, str]:
|
|
|
|
|
|
try:
|
|
|
|
|
|
for udid in ids:
|
|
|
|
|
|
cls.stop(udid)
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(e)
|
|
|
|
|
|
return 200, "停止成功."
|
2025-09-19 19:39:32 +08:00
|
|
|
|
|
2025-09-18 20:09:52 +08:00
|
|
|
|
@classmethod
|
2025-09-22 19:10:58 +08:00
|
|
|
|
def _kill_thread(cls, tid: int) -> bool:
|
|
|
|
|
|
"""向原生线程 ID 抛 KeyboardInterrupt,强制跳出"""
|
|
|
|
|
|
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid),
|
|
|
|
|
|
ctypes.py_object(KeyboardInterrupt))
|
|
|
|
|
|
if res == 0: # 线程已不存在
|
|
|
|
|
|
print("线程不存在")
|
|
|
|
|
|
return False
|
|
|
|
|
|
if res > 1: # 命中多个线程,重置
|
|
|
|
|
|
print("命中了多个线程")
|
|
|
|
|
|
ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), 0)
|
|
|
|
|
|
print("杀死线程成功")
|
|
|
|
|
|
return True
|