不让System.Timers.Timer同一时间多次生成定期事件

本文介绍如何利用System.Timers.Timer类在指定时间间隔触发事件,并通过特定方法确保同一时间间隔内仅有一个事件执行,适用于事件执行时间长且资源独占的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


     System.Timers.Timer 在使用时,每隔一个时间间隔,就会产生一个定期事件,而并不关心上次的产生的事件是否已经完成。

     有时候我们设定的时间间隔很短,但是事件的执行时间可能很长,并且事件执行中的资源只能提供给一个事件单独使用,这时候我们希望一个时间间隔只有一个事件在执行,即在当前事件执行完后,下一个时间间隔才开始,然后再产生下一个事件(如图:时间间隔1---->事件1----->时间间隔2----->事件2   ...)

 

代码如下:

 

System.Timers.Timer timer  =   new  System.Timers.Timer();
timer.Interval 
=   1000 ;
timer.Elapsed 
+=   new    ElapsedEventHandler(timerEvent);

private   void  timerEvent( object  sender, EventArgs e)
{
        ((Timer)sender).Enabled 
=   false ;    //    执行前先停止计时
        
//   do something
        ((Timer)sender).Enabled  =   true ;    //    执行后再开始
}


参考:http://topic.youkuaiyun.com/u/20070425/11/fb78e8a3-03e7-4d82-a54c-8bd6de39f908.html

网站:http://www.91chahao.com/

转载于:https://www.cnblogs.com/joysing/archive/2010/02/25/1672932.html

修改下面代码# 处理01-07的情况的部分,使保存完图片先发送前进命令 (0x02)后进入三秒 UPLOADING = 4 # 上传处理中状态的状态,以保证不会同一张照片多次保存 import logging from maix import camera, display, image, nn, app, uart, time import requests import json import os import threading from datetime import datetime # 日志配置 logging.basicConfig( level=logging.INFO, format='%(asctime)s [%(levelname)s] %(message)s', handlers=[ logging.FileHandler("/root/operation.log"), logging.StreamHandler() ] ) logger = logging.getLogger("MAIX_PRO") # 状态定义 class SystemState: NORMAL = 0 # 正常检测模式 OBJECT_DETECTED = 1 # 物体检测处理中 SPECIAL_HANDLING = 2 # 特殊处理模式(标签08) WAIT_FOR_LABEL1 = 3 # 等待标签1状态 UPLOADING = 4 # 上传处理中状态 PAUSED = 5 # 暂停状态,等待UART信号 # OCR模型加载 try: ocr = nn.PP_OCR(model="/root/models/pp_ocr.mud") logger.info("OCR model loaded") except Exception as e: logger.critical(f"OCR model load failed: {str(e)}") exit(1) # 保存目录 SAVE_DIR = "/boot/Pictures/" os.makedirs(SAVE_DIR, exist_ok=True) # 更新ROI区域定义 (x, y, w, h) - 使用新参数 (138, 139, 44, 85) ROI_X = 138 ROI_Y = 139 ROI_W = 44 ROI_H = 85 # 硬件初始化(使用OCR模型要求的分辨率) try: cam = camera.Camera(ocr.input_width(), ocr.input_height(), ocr.input_format()) logger.debug(f"Camera resolution: {cam.width()}x{cam.height()}") except RuntimeError as e: logger.critical(f"Camera init failed: {str(e)}") exit(1) disp = display.Display() # UART初始化 device = "/dev/ttyS0" serial0 = uart.UART(device, 115200) logger.info("UART initialized") # 使用固定token替换登录流程 token = "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MTkwNTgwNDA0MTExNjU2OTYwMSwidXNlclJvbGUiOiJhZG1pbiIsImV4cCI6ODY0MTc1MjM3MDQzNiwidXNlcm5hbWUiOm51bGx9.3TxID4LJExTSDFxo4jr8LuIgFYgO2cSp7Z3sqPATVc0" logger.info(f"Using fixed token: {token[:10]}...") # 只打印前10位避免日志过长 class OperationController: def __init__(self): self.state = SystemState.NORMAL self.current_label = None self.last_detect_time = 0 self.upload_complete = False self.lock = threading.Lock() self.timers = [] # 初始发送forward命令 (0x02) self.send_uart("right") # 初始化 photo_url 及 data_url self.photo_url = "http://111.230.114.23/api/file/upload" self.data_url = "http://111.230.114.23/api/data/add" # 使用固定token self.token = token # 启动UART接收线程 self.uart_receive_thread = threading.Thread(target=self.uart_receive_loop, daemon=True) self.uart_receive_thread.start() logger.info("UART receive thread started") def uart_receive_loop(self): """UART接收线程,处理接收到的数据""" while True: try: # 读取UART数据 data = serial0.read(1) # 每次读取一个字节 if data is not None and len(data) > 0: # 将字节转换为整数 byte_val = data[0] logger.info(f"UART received byte: {hex(byte_val)}") if byte_val == 0x02: # 收到0x02时重置状态为NORMAL with self.lock: logger.info("Received 0x02, reset state to NORMAL") self.state = SystemState.NORMAL # 发送前进命令 self.send_uart("right") except Exception as e: logger.error(f"UART receive error: {str(e)}") time.sleep_ms(10) # 避免过度占用CPU def send_uart(self, command): """发送带十六进制前缀的UART命令,命令为单字节""" # 如果当前处于上传状态,则不发送任何UART命令 if self.state == SystemState.UPLOADING: logger.warning(f"Blocked UART command during upload: {command}") return try: # 命令映射表 command_map = { "stop": 0x00, # 停止命令 "left": 0x01, # 左转命令 "right": 0x02 # 右转/前进命令 } # 获取命令对应的字节值 if command in command_map: cmd_byte = bytes([command_map[command]]) else: logger.error(f"Unknown command: {command}") return # 创建十六进制前缀字节序列 header = bytes.fromhex('ffff02') # 组合所有部分:header + cmd_byte data_to_send = header + cmd_byte # 发送完整的字节序列 serial0.write(data_to_send) logger.info(f"UART sent: {data_to_send.hex()} (hex)") except Exception as e: logger.error(f"UART send failed: {str(e)}") def save_and_upload(self, img, label): try: # 设置上传状态,阻止UART发送 self.state = SystemState.UPLOADING logger.info(f"Starting upload for label {label} (UART blocked)") # 生成文件名 timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"{SAVE_DIR}{label}_{timestamp}.jpg" # 保存图片 if img.save(filename, quality=90): logger.info(f"Image saved: {filename}") # 同步上传 with open(filename, 'rb') as file: files = { 'file': ('image.jpg', file, 'image/jpeg') } params = { 'biz': 'plant_picture', } headers = { "token": self.token } logger.info(f"Uploading {filename} with label {label}, Token: {self.token[:10]}...") response = requests.post( self.photo_url, files=files, headers=headers, params=params ) if response.json().get('code') == 0: logger.info(f"Upload success: {filename}, Response: {response.text}") return response.json().get('data') else: logger.warning(f"Upload failed: {response.text}") else: logger.error("Image save failed") except Exception as e: logger.error(f"Capture failed: {str(e)}") finally: # 恢复状态,允许UART发送 self.state = SystemState.NORMAL logger.info(f"Upload completed for label {label} (UART unblocked)") return None def save_data(self, data): try: # 设置上传状态,阻止UART发送 self.state = SystemState.UPLOADING logger.info("Starting data save (UART blocked)") params = [{ "deviceName": 1, "plantId": 1, "growthStage": "flowering", "healthStage": "healthy", "height": "5", "crownWidth": "5", "humidity": '', "ph": '', "dan": '', "lin": '', "jia": '', "photoUrl": data, "notes": "" }] headers = { "token": self.token } response = requests.post( self.data_url, headers=headers, json=params ) logger.info(f"Response: {data}") if response.json().get('code') == 0: logger.info(f"Data save success: {response.text}") else: logger.warning(f"Data save failed: {response.text}") except Exception as e: logger.error(f"Data upload error: {str(e)}") finally: # 恢复状态,允许UART发送 self.state = SystemState.NORMAL logger.info("Data save completed (UART unblocked)") def get_ocr_text(self, obj): """安全获取OCR文本内容""" try: # 尝试获取文本内容 text = obj.char_str # 如果char_str是方法则调用它 if callable(text): text = text() # 确保是字符串类型 return str(text).strip() except Exception as e: logger.error(f"获取OCR文本失败: {str(e)}") return "" def handle_detection(self, objs, img): with self.lock: current_time = time.time() # 状态机逻辑 if self.state == SystemState.NORMAL: for obj in objs: # 使用安全方法获取文本 text = self.get_ocr_text(obj) logger.info(f"OCR detected text: {text}") # 处理01-07的情况 if text in ["01", "02", "03", "04", "05", "06", "07"]: num = int(text) # 转换为整数 logger.info(f"Label {num} detected via OCR") self.state = SystemState.OBJECT_DETECTED self.send_uart("stop") # 发送停止命令 (0x00) # 1秒后保存并上传 def delayed_save(): data = self.save_and_upload(img, num) if data: self.save_data(data) self.add_timer(1.0, delayed_save) # 2秒后发送前进命令 def delayed_forward(): self.send_uart("right") # 发送前进命令 (0x02) self.state = SystemState.NORMAL self.add_timer(2.0, delayed_forward) break # 处理一个有效结果后退出循环 # 处理08的情况 elif text == "08": logger.info("Special label 08 detected") self.state = SystemState.SPECIAL_HANDLING self.send_uart("stop") # 发送停止命令 (0x00) # 1秒后保存并上传 def delayed_save(): data = self.save_and_upload(img, 8) if data: self.save_data(data) self.send_uart("left") # 发送左转命令 (0x01) # 进入等待标签1状态 self.state = SystemState.WAIT_FOR_LABEL1 self.add_timer(1.0, delayed_save) break # 处理一个有效结果后退出循环 elif self.state == SystemState.SPECIAL_HANDLING: # 等待上传完成 pass elif self.state == SystemState.WAIT_FOR_LABEL1: for obj in objs: text = self.get_ocr_text(obj) if text == "01": logger.info("Label1 after special handling") self.send_uart("stop") # 发送停止命令 (0x00) break def add_timer(self, delay, callback): timer = threading.Timer(delay, callback) timer.start() self.timers.append(timer) def cleanup(self): for timer in self.timers: timer.cancel() logger.info("System cleanup completed") # 主控制实例 controller = OperationController() # 创建颜色对象 red_color = image.Color(255, 0, 0) # 红色 - 用于检测框 green_color = image.Color(0, 255, 0) # 绿色 - 用于ROI框 blue_color = image.Color(0, 0, 255) # 蓝色 - 用于文本 yellow_color = image.Color(255, 255, 0) # 黄色 - 用于警告信息 # 主循环 try: # 帧率计算变量 frame_count = 0 last_log_time = time.time() while not app.need_exit(): try: # 读取图像 img = cam.read() frame_count += 1 except Exception as e: logger.error(f"摄像头读取失败: {str(e)}") continue # 绘制ROI区域边框 - 使用新的矩形参数 (138, 139, 44, 85) img.draw_rect(ROI_X, ROI_Y, ROI_W, ROI_H, green_color, thickness=2) # 添加ROI区域标签 img.draw_string(ROI_X, ROI_Y - 20, f"ROI: {ROI_X},{ROI_Y},{ROI_W},{ROI_H}", scale=0.7, color=blue_color) # 裁剪ROI区域 try: # 使用crop方法裁剪ROI区域 roi_img = img.crop(ROI_X, ROI_Y, ROI_W, ROI_H) except Exception as e: logger.error(f"ROI裁剪失败: {str(e)}") disp.show(img) continue # 执行OCR识别(仅在ROI区域) try: objs = ocr.detect(roi_img) except Exception as e: logger.error(f"OCR识别失败: {str(e)}") disp.show(img) continue # 调整检测框坐标(从ROI坐标转换到原始图像坐标) adjusted_objs = [] for obj in objs: # 直接修改原始对象坐标 obj.box.x1 += ROI_X obj.box.y1 += ROI_Y obj.box.x2 += ROI_X obj.box.y2 += ROI_Y obj.box.x3 += ROI_X obj.box.y3 += ROI_Y obj.box.x4 += ROI_X obj.box.y4 += ROI_Y adjusted_objs.append(obj) # 处理结果 if len(adjusted_objs) > 0: controller.handle_detection(adjusted_objs, img) # 显示OCR结果 for obj in adjusted_objs: # 绘制检测框(四个点) points = obj.box.to_list() img.draw_keypoints( points, red_color, # 颜色 4, # 点大小 -1, # 连接所有点 1 # 线宽 ) # 安全获取文本内容 try: text = controller.get_ocr_text(obj) # 绘制识别文本 img.draw_string( obj.box.x4, obj.box.y4, text, scale=0.5, color=red_color ) except Exception as e: logger.error(f"绘制OCR文本失败: {str(e)}") img.draw_string( obj.box.x4, obj.box.y4, "ERROR", scale=0.5, color=yellow_color ) # 显示状态信息 state_text = f"State: {controller.state}" img.draw_string(5, 5, state_text, scale=0.8, color=blue_color) # 显示检测结果数量 count_text = f"Detected: {len(adjusted_objs)}" img.draw_string(5, 25, count_text, scale=0.8, color=blue_color) # 显示当前时间 time_text = datetime.now().strftime("%H:%M:%S") img.draw_string(img.width() - 100, 5, time_text, scale=0.8, color=blue_color) # 显示帧率 if time.time() - last_log_time > 1.0: fps = frame_count img.draw_string(5, 45, f"FPS: {fps}", scale=0.8, color=blue_color) frame_count = 0 last_log_time = time.time() # 显示图像 disp.show(img) except KeyboardInterrupt: logger.info("用户中断") except Exception as e: logger.critical(f"致命错误: {str(e)}") finally: controller.cleanup() logger.info("系统关闭")
07-14
理解下面maixcam代码,修改代码1里的yolo5模型识别逻辑改成代码2的ocr模型识别逻辑。当ocr识别到01、02、03、04、05、06、07时,运行代码1的elif 1 <= obj.class_id <= 18逻辑。当ocr识别到08,执行if obj.class_id == 19的逻辑,接着执行SystemState.WAIT_FOR_LABEL1的逻辑。这里的运行代码1的elif 1 <= obj.class_id <= 18逻辑是指直接修改代码1里的条件使逻辑运行。 代码1:import logging from maix import camera, display, image, nn, app, uart, time import requests import json import os import threading from datetime import datetime 日志配置 logging.basicConfig( level=logging.INFO, format=‘%(asctime)s [%(levelname)s] %(message)s’, handlers=[ logging.FileHandler(“/root/operation.log”), logging.StreamHandler() ] ) logger = logging.getLogger(“MAIX_PRO”) 状态定义 class SystemState: NORMAL = 0 # 正常检测模式 OBJECT_DETECTED = 1 # 物体检测处理中 SPECIAL_HANDLING = 2# 特殊处理模式(标签19) WAIT_FOR_LABEL1 = 3 # 等待标签1状态 模型加载 try: detector = nn.YOLOv5(model=“/root/models/mymodels/model_195130.mud”, dual_buff=True) logger.info(“YOLOv5 model loaded”) except Exception as e: logger.critical(f"Model load failed: {str(e)}") exit(1) 保存目录 SAVE_DIR = “/root/models/mymodel/” SAVE_DIR = “/boot/Pictures/” os.makedirs(SAVE_DIR, exist_ok=True) 硬件初始化(调整为硬件支持的分辨率) try: cam = camera.Camera(width=1080, height=640) # 使用标准VGA分辨率 logger.debug(f"Camera resolution: {cam.width()}x{cam.height()}“) except RuntimeError as e: logger.critical(f"Camera init failed: {str(e)}”) exit(1) disp = display.Display() UART初始化 device = “/dev/ttyS0” serial0 = uart.UART(device, 38400) logger.info(“UART initialized”) 登录获取token login_url = “http://111.230.114.23/api/user/login” headers_login = {‘Content-Type’: ‘application/json’} login_data = {“userAccount”: “lanyating”, “userPassword”: 12345678} json_data = json.dumps(login_data) try: login_response = requests.post(login_url, data=json_data, headers=headers_login) response_json = login_response.json() token = response_json.get(‘data’) if token: logger.info(f"Login successful, token obtained: {token[:10]}…“) # 只显示部分token以保护隐私 else: logger.error(f"Login failed: No token returned in response”) exit(1) except Exception as e: logger.critical(f"Login failed: {str(e)}") exit(1) def send_uart(data): try: serial0.write_str(data + “\n”) logger.info(f"UART sent: {data}“) except Exception as e: logger.error(f"UART send failed: {str(e)}”) class OperationController: def init(self): self.state = SystemState.NORMAL self.current_label = None self.last_detect_time = 0 self.upload_complete = False self.lock = threading.Lock() self.timers = [] # 初始发送forward self.send_uart("forward") # 初始化 photo_url 和 data_url self.photo_url = "http://111.230.114.23/api/file/upload" self.data_url = "http://111.230.114.23/api/data/add" # 确保 token 在整个类中可用 self.token = token def send_uart(self, command): try: serial0.write_str(command + "\n") logger.info(f"UART sent: {command}") except Exception as e: logger.error(f"UART send failed: {str(e)}") def save_and_upload(self, img, label): try: # 生成文件名 timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"{SAVE_DIR}{label}_{timestamp}.jpg" # 保存图片 if img.save(filename, quality=90): logger.info(f"Image saved: {filename}") # 同步上传 with open(filename, 'rb') as file: files = { 'file': ('image.jpg', file, 'image/jpeg') } params = { 'biz': 'plant_picture', } headers = { "token": self.token } logger.info(f"Uploading {filename} with label {label}, Token: {self.token[:10]}...") response = requests.post( self.photo_url, files=files, headers=headers, params=params ) if response.json().get('code') == 0 : logger.info(f"Upload success: {filename}, Response: {response.text}") return response.json().get('data') else: logger.warning(f"Upload failed: {response.text}") else: logger.error("Image save failed") except Exception as e: logger.error(f"Capture failed: {str(e)}") return None def save_data(self, data): try: params = [{ "deviceName": 1, "plantId": 1, "growthStage": "flowering", "healthStage": "healthy", "height": "5", "crownWidth": "5", "humidity": '', "ph": '', "dan": '', "lin": '', "jia": '', "photoUrl": data, "notes": "" }] headers = { "token": self.token } response = requests.post( self.data_url, headers=headers, json=params ) logger.info(f"Response: {data}") if response.json().get('code') == 0 : logger.info(f"Data save success: {response.text}") else: logger.warning(f"Data save failed: {response.text}") except Exception as e: logger.error(f"Data upload error: {str(e)}") def handle_detection(self, objs, img): with self.lock: current_time = time.time() # 状态机逻辑 if self.state == SystemState.NORMAL: for obj in objs: if obj.class_id == 19: logger.info("Special label 19 detected") self.state = SystemState.SPECIAL_HANDLING self.send_uart("stop") # 1秒后保存并上传 def delayed_save(): print("开始上传") data = self.save_and_upload(img, 19) print("上传成功") if data: self.save_data(data) self.send_uart("back") self.add_timer(1.0, delayed_save) break elif 1 <= obj.class_id <= 18: logger.info(f"Label {obj.class_id} detected") self.state = SystemState.OBJECT_DETECTED self.send_uart("stop") # 1秒后保存并上传 def delayed_save(): print("开始上传") data = self.save_and_upload(img, obj.class_id) print("上传成功") if data: self.save_data(data) self.add_timer(1.0, delayed_save) # 2秒后发送forward def delayed_forward(): self.send_uart("forward") self.state = SystemState.NORMAL self.add_timer(2.0, delayed_forward) break elif self.state == SystemState.SPECIAL_HANDLING: # 等待上传完成 pass # 在同步上传的情况下不需要等待标志位 elif self.state == SystemState.WAIT_FOR_LABEL1: for obj in objs: if obj.class_id == 1: logger.info("Label1 after special handling") self.send_uart("stop") self.add_timer(1.0, lambda: self.send_uart("forward")) self.state = SystemState.NORMAL break def add_timer(self, delay, callback): timer = threading.Timer(delay, callback) timer.start() self.timers.append(timer) def cleanup(self): for timer in self.timers: timer.cancel() logger.info("System cleanup completed") 主控制实例 controller = OperationController() 创建 Color 对象 red_color = image.Color(255, 0, 0) # 定义标准红色 主循环 try: while not app.need_exit(): try: img = cam.read() except Exception as e: logger.error(f"摄像头读取失败: {str(e)}") continue # 执行检测 try: objs = detector.detect(img, conf_th=0.6) except Exception as e: logger.error(f"目标检测失败: {str(e)}") disp.show(img) continue # 处理结果 if len(objs) > 0: controller.handle_detection(objs, img) # 显示画面 for obj in objs: # 绘制检测框(使用位置参数) img.draw_rect( obj.x, obj.y, obj.w, obj.h, red_color, # 颜色参数位置 2 # 线宽参数位置 ) # 绘制标签文本 img.draw_string( obj.x, obj.y, f"{detector.labels[obj.class_id]} {obj.score:.2f}", scale=0.5, color=red_color ) disp.show(img) except KeyboardInterrupt: logger.info(“用户中断”) except Exception as e: logger.critical(f"致命错误: {str(e)}") finally: controller.cleanup() logger.info(“系统关闭”) 代码2:from maix import camera, display, image, nn, app, time, touchscreen def is_in_button(x, y, btn_pos): return x > btn_pos[0] and x < btn_pos[0] + btn_pos[2] and y > btn_pos[1] and y < btn_pos[1] + btn_pos[3] def main(disp): model = “/root/models/pp_ocr.mud” ocr = nn.PP_OCR(model) cam = camera.Camera(ocr.input_width(), ocr.input_height(), ocr.input_format()) ts = touchscreen.TouchScreen() img_back = image.load("/maixapp/share/icon/ret.png") back_rect = [0, 0, 32, 32] back_rect_disp = image.resize_map_pos(cam.width(), cam.height(), disp.width(), disp.height(), image.Fit.FIT_CONTAIN, back_rect[0], back_rect[1], back_rect[2], back_rect[3]) image.load_font("ppocr", "/maixapp/share/font/ppocr_keys_v1.ttf", size = 20) image.set_default_font("ppocr") while not app.need_exit(): img = cam.read() objs = ocr.detect(img) for obj in objs: points = obj.box.to_list() img.draw_keypoints(points, image.COLOR_RED, 4, -1, 1) img.draw_string(obj.box.x4, obj.box.y4, obj.char_str(), image.COLOR_RED) img.draw_image(0, 0, img_back) disp.show(img) x, y, pressed = ts.read() if is_in_button(x, y, back_rect_disp): app.set_exit_flag(True) if name == ‘main’: screen = display.Display() try: main(screen) except Exception: import traceback e = traceback.format_exc() print(e) img = image.Image(screen.width(), screen.height()) img.draw_string(2, 2, e, image.COLOR_WHITE, font=“hershey_complex_small”, scale=0.6) screen.show(img) while not app.need_exit(): time.sleep(0.2)
07-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值