等待时间 single-task message

         昨天在快要下班的时候,我的同事突然碰到一个问题,说一个只需要执行几十秒钟的procedure,居然跑了半个小时都还没有完。我不相信,然后我也去跑了一下,果然是这样,由于当时马上下班啦,我就跟我同事说,我明天来帮你看。

最开始我以为是锁表的原因,跑这个procedure,查看v$locked_objects为空,没有一条记录,,然后再查看当前session如下:

 

发现有条sql始终卡在那里,并且等待时间为single-task message,通过查询资料了解到这个事件在10g中通常是dblink导致的。然后马上去重建一下synonym,因为这个存储过程中所需表是通过dblink来同义词,发现建一个同义词都需要2分钟,并且这张表的记录只有几百条,坑爹啊。

 

重建一下dblink,结果还是如此,再去查看一下最新的tns,结果发现tns的server已经发生改变,我估计多半是连接到backup的server上啦。

最后再次重建dblink,问题解决,结果该procedure几秒钟完成。

 

总结一下:在10g中,碰到single-task message事件,基本上是有dblink造成的,更甚会进一步产生Mutex等待。

 

 

/* * SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ /* * The following example demonstrates a master node in a TWAI network. The master * node is responsible for initiating and stopping the transfer of data messages. * The example will execute multiple iterations, with each iteration the master * node will do the following: * 1) Start the TWAI driver * 2) Repeatedly send ping messages until a ping response from slave is received * 3) Send start command to slave and receive data messages from slave * 4) Send stop command to slave and wait for stop response from slave * 5) Stop the TWAI driver */ #include <stdio.h> #include <stdlib.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "freertos/semphr.h" #include "esp_err.h" #include "esp_log.h" #include "driver/twai.h" /* --------------------- Definitions and static variables ------------------ */ //Example Configuration #define PING_PERIOD_MS 250 #define NO_OF_DATA_MSGS 50 #define NO_OF_ITERS 3 #define ITER_DELAY_MS 1000 #define RX_TASK_PRIO 8 #define TX_TASK_PRIO 9 #define CTRL_TSK_PRIO 10 #define TX_GPIO_NUM CONFIG_EXAMPLE_TX_GPIO_NUM #define RX_GPIO_NUM CONFIG_EXAMPLE_RX_GPIO_NUM #define EXAMPLE_TAG "TWAI Master" #define ID_MASTER_STOP_CMD 0x0A0 #define ID_MASTER_START_CMD 0x0A1 #define ID_MASTER_PING 0x0A2 #define ID_SLAVE_STOP_RESP 0x0B0 #define ID_SLAVE_DATA 0x0B1 #define ID_SLAVE_PING_RESP 0x0B2 typedef enum { TX_SEND_PINGS, TX_SEND_START_CMD, TX_SEND_STOP_CMD, TX_TASK_EXIT, } tx_task_action_t; typedef enum { RX_RECEIVE_PING_RESP, RX_RECEIVE_DATA, RX_RECEIVE_STOP_RESP, RX_TASK_EXIT, } rx_task_action_t; static const twai_timing_config_t t_config = TWAI_TIMING_CONFIG_25KBITS(); static const twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL(); static const twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(TX_GPIO_NUM, RX_GPIO_NUM, TWAI_MODE_NORMAL); static const twai_message_t ping_message = { // Message type and format settings .extd = 0, // Standard Format message (11-bit ID) .rtr = 0, // Send a data frame .ss = 1, // Is single shot (won't retry on error or NACK) .self = 0, // Not a self reception request .dlc_non_comp = 0, // DLC is less than 8 // Message ID and payload .identifier = ID_MASTER_PING, .data_length_code = 0, .data = {0}, }; static const twai_message_t start_message = { // Message type and format settings .extd = 0, // Standard Format message (11-bit ID) .rtr = 0, // Send a data frame .ss = 0, // Not single shot .self = 0, // Not a self reception request .dlc_non_comp = 0, // DLC is less than 8 // Message ID and payload .identifier = ID_MASTER_START_CMD, .data_length_code = 0, .data = {0}, }; static const twai_message_t stop_message = { // Message type and format settings .extd = 0, // Standard Format message (11-bit ID) .rtr = 0, // Send a data frame .ss = 0, // Not single shot .self = 0, // Not a self reception request .dlc_non_comp = 0, // DLC is less than 8 // Message ID and payload .identifier = ID_MASTER_STOP_CMD, .data_length_code = 0, .data = {0}, }; static QueueHandle_t tx_task_queue; static QueueHandle_t rx_task_queue; static SemaphoreHandle_t stop_ping_sem; static SemaphoreHandle_t ctrl_task_sem; static SemaphoreHandle_t done_sem; /* --------------------------- Tasks and Functions -------------------------- */ static void twai_receive_task(void *arg) { while (1) { rx_task_action_t action; xQueueReceive(rx_task_queue, &action, portMAX_DELAY); if (action == RX_RECEIVE_PING_RESP) { //Listen for ping response from slave while (1) { twai_message_t rx_msg; twai_receive(&rx_msg, portMAX_DELAY); if (rx_msg.identifier == ID_SLAVE_PING_RESP) { xSemaphoreGive(stop_ping_sem); xSemaphoreGive(ctrl_task_sem); break; } } } else if (action == RX_RECEIVE_DATA) { //Receive data messages from slave uint32_t data_msgs_rec = 0; while (data_msgs_rec < NO_OF_DATA_MSGS) { twai_message_t rx_msg; twai_receive(&rx_msg, portMAX_DELAY); if (rx_msg.identifier == ID_SLAVE_DATA) { uint32_t data = 0; for (int i = 0; i < rx_msg.data_length_code; i++) { data |= (rx_msg.data[i] << (i * 8)); } ESP_LOGI(EXAMPLE_TAG, "Received data value %"PRIu32, data); data_msgs_rec ++; } } xSemaphoreGive(ctrl_task_sem); } else if (action == RX_RECEIVE_STOP_RESP) { //Listen for stop response from slave while (1) { twai_message_t rx_msg; twai_receive(&rx_msg, portMAX_DELAY); if (rx_msg.identifier == ID_SLAVE_STOP_RESP) { xSemaphoreGive(ctrl_task_sem); break; } } } else if (action == RX_TASK_EXIT) { break; } } vTaskDelete(NULL); } static void twai_transmit_task(void *arg) { while (1) { tx_task_action_t action; xQueueReceive(tx_task_queue, &action, portMAX_DELAY); if (action == TX_SEND_PINGS) { //Repeatedly transmit pings ESP_LOGI(EXAMPLE_TAG, "Transmitting ping"); while (xSemaphoreTake(stop_ping_sem, 0) != pdTRUE) { twai_transmit(&ping_message, portMAX_DELAY); vTaskDelay(pdMS_TO_TICKS(PING_PERIOD_MS)); } } else if (action == TX_SEND_START_CMD) { //Transmit start command to slave twai_transmit(&start_message, portMAX_DELAY); ESP_LOGI(EXAMPLE_TAG, "Transmitted start command"); } else if (action == TX_SEND_STOP_CMD) { //Transmit stop command to slave twai_transmit(&stop_message, portMAX_DELAY); ESP_LOGI(EXAMPLE_TAG, "Transmitted stop command"); } else if (action == TX_TASK_EXIT) { break; } } vTaskDelete(NULL); } static void twai_control_task(void *arg) { xSemaphoreTake(ctrl_task_sem, portMAX_DELAY); tx_task_action_t tx_action; rx_task_action_t rx_action; for (int iter = 0; iter < NO_OF_ITERS; iter++) { ESP_ERROR_CHECK(twai_start()); ESP_LOGI(EXAMPLE_TAG, "Driver started"); //Start transmitting pings, and listen for ping response tx_action = TX_SEND_PINGS; rx_action = RX_RECEIVE_PING_RESP; xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY); xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY); //Send Start command to slave, and receive data messages xSemaphoreTake(ctrl_task_sem, portMAX_DELAY); tx_action = TX_SEND_START_CMD; rx_action = RX_RECEIVE_DATA; xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY); xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY); //Send Stop command to slave when enough data messages have been received. Wait for stop response xSemaphoreTake(ctrl_task_sem, portMAX_DELAY); tx_action = TX_SEND_STOP_CMD; rx_action = RX_RECEIVE_STOP_RESP; xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY); xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY); xSemaphoreTake(ctrl_task_sem, portMAX_DELAY); ESP_ERROR_CHECK(twai_stop()); ESP_LOGI(EXAMPLE_TAG, "Driver stopped"); vTaskDelay(pdMS_TO_TICKS(ITER_DELAY_MS)); } //Stop TX and RX tasks tx_action = TX_TASK_EXIT; rx_action = RX_TASK_EXIT; xQueueSend(tx_task_queue, &tx_action, portMAX_DELAY); xQueueSend(rx_task_queue, &rx_action, portMAX_DELAY); //Delete Control task xSemaphoreGive(done_sem); vTaskDelete(NULL); } void app_main(void) { //Create tasks, queues, and semaphores rx_task_queue = xQueueCreate(1, sizeof(rx_task_action_t)); tx_task_queue = xQueueCreate(1, sizeof(tx_task_action_t)); ctrl_task_sem = xSemaphoreCreateBinary(); stop_ping_sem = xSemaphoreCreateBinary(); done_sem = xSemaphoreCreateBinary(); xTaskCreatePinnedToCore(twai_receive_task, "TWAI_rx", 4096, NULL, RX_TASK_PRIO, NULL, tskNO_AFFINITY); xTaskCreatePinnedToCore(twai_transmit_task, "TWAI_tx", 4096, NULL, TX_TASK_PRIO, NULL, tskNO_AFFINITY); xTaskCreatePinnedToCore(twai_control_task, "TWAI_ctrl", 4096, NULL, CTRL_TSK_PRIO, NULL, tskNO_AFFINITY); //Install TWAI driver ESP_ERROR_CHECK(twai_driver_install(&g_config, &t_config, &f_config)); ESP_LOGI(EXAMPLE_TAG, "Driver installed"); xSemaphoreGive(ctrl_task_sem); //Start control task xSemaphoreTake(done_sem, portMAX_DELAY); //Wait for completion //Uninstall TWAI driver ESP_ERROR_CHECK(twai_driver_uninstall()); ESP_LOGI(EXAMPLE_TAG, "Driver uninstalled"); //Cleanup vQueueDelete(rx_task_queue); vQueueDelete(tx_task_queue); vSemaphoreDelete(ctrl_task_sem); vSemaphoreDelete(stop_ping_sem); vSemaphoreDelete(done_sem); } 增强上述代码可读性,将添加注释后的代码发出
10-30
class AsyncSocketManager: """异步Socket管理器 - 协调Reader和Writer线程""" # 分批连接参数 BATCH_SIZE = 250 # 每批处理的连接数 BATCH_INTERVAL = 20.0 # 批次间隔时间(秒) MAX_RETRIES = 5 # 增加最大重试次数 RECONNECT_INITIAL_DELAY = 20.0 # 初始重连延迟 RECONNECT_BACKOFF_FACTOR = 1.5 # 指数退避因子 MAX_RECONNECT_DELAY = 120.0 # 最大重连延迟(2分钟) HEALTH_CHECK_INTERVAL = 5.0 # 健康检查间隔 def __init__(self): self.running = True self._shutdown_event = asyncio.Event() self._cleanup_lock = asyncio.Lock() self.shutdown_requested = asyncio.Event() self.original_sigint_handler = None self.shutdown_requested = asyncio.Event() self.server_config = {'ip': 'charge.b-conn.com', 'port': 5455} self.total = 0 self.writer = None self.reader = None self._active_tasks = set() self.connections: Dict[str, Dict] = {} self.batch_tasks: List[asyncio.Task] = [] # 批次任务列表 self._read_lock = asyncio.Lock() # 读取操作专用锁 self._write_lock = asyncio.Lock() # 写入操作专用锁 self._state_lock = asyncio.Lock() # 状态变更锁 self.logger = logging.getLogger(__name__) self.setup_logging() self.connection_pool = {} # 连接池 # 连接状态统计 self.stats = { "success": 0, "failed": 0, "pending": 0, "active": 0 } # 每个连接一个专用的状态锁 self.connection_locks = defaultdict(asyncio.Lock) def install_signal_handlers(self): """安装信号处理器""" try: loop = asyncio.get_running_loop() # 保存原始信号处理器 self.original_sigint_handler = loop.add_signal_handler( signal.SIGINT, self._initiate_shutdown ) self.logger.info("✅ 信号处理器安装完成") except (NotImplementedError, RuntimeError): # 在某些平台上可能不支持 self.logger.warning("⚠️ 当前平台不支持异步信号处理") def _initiate_shutdown(self): """初始化关闭过程""" self.logger.info("🔄 接收到关闭信号,开始优雅关闭...") self.shutdown_requested.set() def restore_signal_handlers(self): """恢复原始信号处理器""" try: loop = asyncio.get_running_loop() if self.original_sigint_handler is not None: loop.remove_signal_handler(signal.SIGINT) # 重新安装默认处理器 loop.add_signal_handler(signal.SIGINT, signal.default_int_handler) except Exception as e: self.logger.debug(f"恢复信号处理器时发生异常: {e}") async def close_all_connections(self): """异步关闭所有Socket连接""" self.logger.info("正在关闭所有Socket连接...") self.running = False self._shutdown_event.set() # 取消所有活跃任务 for task in self._active_tasks: if not task.done(): task.cancel() # 关闭所有连接 close_tasks = [] for pileCode in list(self.connections.keys()): conn = self.connections[pileCode] if 'writer' in conn and conn['writer'] is not None: writer = conn['writer'] close_tasks.append(self.close_writer(writer, pileCode)) if close_tasks: await asyncio.gather(*close_tasks, return_exceptions=True) self.logger.info("所有连接已关闭") async def close_writer(self, writer, pileCode: str): """安全关闭写入器""" try: if not writer.is_closing(): writer.close() await writer.wait_closed() self.logger.debug(f"关闭连接: {pileCode}") except Exception as e: self.logger.error(f"关闭连接失败: {pileCode} 错误: {e}") async def _close_single_connection(self, conn_key: str): """关闭单个Socket连接""" try: if conn_key in self.connections: conn_info = self.connections[conn_key] # 实际的Socket关闭逻辑 if 'writer' in conn_info: writer = conn_info['writer'] writer.close() await writer.wait_closed() self.logger.debug(f"🔌 关闭连接 {conn_key}") del self.connections[conn_key] except Exception as e: self.logger.error(f"❌ 关闭连接 {conn_key} 时发生异常: {e}") async def batch_create_connections(self, pile_codes: List[str]): """添加健康监控器""" # 启动健康监控器 health_task = asyncio.create_task( self.connection_health_monitor(), name="connection_health_monitor" ) self.batch_tasks.append(health_task) """批量创建Socket连接(分批处理)""" total = len(pile_codes) batches = math.ceil(total / self.BATCH_SIZE) self.total_connections = total self.logger.info(f"开始分批创建连接,共{total}个桩号,分{batches}批处理,每批{self.BATCH_SIZE}个") for batch_num in range(batches): if self.shutdown_requested.is_set(): self.logger.warning("关闭信号已触发,停止创建新批次") break start_idx = batch_num * self.BATCH_SIZE end_idx = min(start_idx + self.BATCH_SIZE, total) batch = pile_codes[start_idx:end_idx] batch_id = batch_num + 1 self.logger.info(f"处理批次 {batch_id}/{batches} ({len(batch)}个桩号)") # 创建批量连接任务 task = asyncio.create_task( self.process_batch(batch, batch_id), name=f"batch_{batch_id}" ) self.batch_tasks.append(task) # 添加批次间隔 if batch_num < batches - 1: await asyncio.sleep(self.BATCH_INTERVAL) # 等待所有批次完成 if self.batch_tasks: await asyncio.gather(*self.batch_tasks) self.logger.info(f"所有批次处理完成! 成功:{self.stats['success']} 失败:{self.stats['failed']}") async def process_batch(self, pile_codes: List[str], batch_id: int): """处理单个批次的连接""" tasks = [] for i, pileCode in enumerate(pile_codes): message_id = f"batch{batch_id}-conn{i + 1}" task = asyncio.create_task( self.socket_worker(message_id, pileCode), name=f"batch{batch_id}-{pileCode}" ) tasks.append(task) self.connection_pool[pileCode] = {"status": "pending"} self.stats["pending"] += 1 # 等待批次内所有连接完成初始化 results = await asyncio.gather(*tasks, return_exceptions=True) # 统计批次结果 for result in results: if isinstance(result, Exception): self.stats["failed"] += 1 else: self.stats["success"] += 1 self.stats["pending"] -= len(pile_codes) self.stats["active"] = len(self.connections) async def socket_worker(self, message_id: str, pileCode: str): global logger """异步Socket工作协程""" retry_count = 0 last_reconnect_time = 0 # health_check_last = time.time() while self.running and not self._shutdown_event.is_set(): try: # 检查是否需要等待重连延迟 current_time = time.time() if last_reconnect_time > 0: delay = self.calculate_reconnect_delay(retry_count) if current_time - last_reconnect_time < delay: await asyncio.sleep(delay - (current_time - last_reconnect_time)) # 尝试创建连接 success = await self.create_socket_connection_with_retry(message_id, pileCode, retry_count) if not success: retry_count = min(retry_count + 1, self.MAX_RETRIES) last_reconnect_time = time.time() continue # 重置重试计数(连接成功) retry_count = 0 last_reconnect_time = 0 # 启动读写任务 await self.start_reader_writer(message_id, pileCode) # 健康检查和状态报告 # current_time = time.time() # if current_time - health_check_last > self.HEALTH_CHECK_INTERVAL: # pending_count = self.stats["pending"] # self.logger.info( # f"等待中={pending_count} 重试={retry_count}" # ) # health_check_last = current_time except asyncio.CancelledError: self.logger.info(f"⚠️ Socket工作协程被取消: {message_id}") if pileCode in self.connections: conn = self.connections[pileCode] if 'writer' in conn and conn['writer'] is not None: writer = conn['writer'] try: if not writer.is_closing(): writer.close() await writer.wait_closed() except Exception: pass if pileCode in self.connections: del self.connections[pileCode] break except Exception as e: self.logger.error(f"❌ Socket工作异常: {message_id} 桩号: {pileCode} 错误: {e}") retry_count = min(retry_count + 1, self.MAX_RETRIES) last_reconnect_time = time.time() # 清理当前连接 if pileCode in self.connections: conn = self.connections[pileCode] if 'writer' in conn and conn['writer'] is not None: writer = conn['writer'] try: if not writer.is_closing(): writer.close() await writer.wait_closed() except Exception: pass if pileCode in self.connections: del self.connections[pileCode] await asyncio.sleep(1) # 短暂暂停 finally: # 更新连接池状态 if pileCode in self.connection_pool: self.connection_pool[pileCode] = { "status": "retrying" if retry_count > 0 else "active", "retry_count": retry_count, "last_retry": last_reconnect_time } def calculate_reconnect_delay(self, retry_count: int) -> float: """计算指数退避的重连延迟""" delay = self.RECONNECT_INITIAL_DELAY * (self.RECONNECT_BACKOFF_FACTOR ** retry_count) return min(delay, self.MAX_RECONNECT_DELAY) def handle_task_completion(self, task: asyncio.Task): """任务完成回调处理""" try: # 首先检查任务是否被取消 if task.cancelled(): self.logger.debug(f"任务 {task.get_name()} 被取消") return if task.done() and task.exception(): self.logger.error(f"任务失败: {task.get_name()} {task.exception()}") # 标记连接需要重启 pile_code = task.get_name().split("_")[1] if pile_code in self.connections: writer = self.connections[pile_code]["writer"] if writer is not None: writer.close() if pile_code in self.connections: del self.connections[pile_code] except Exception as e: self.logger.error(f"任务回调处理错误: {e}") async def connection_health_monitor(self): """连接健康监控器""" while self.running and not self._shutdown_event.is_set(): try: real_active_count = 0 current_time = time.time() connections_to_restart = [] for pile_code, conn in list(self.connections.items()): # 检查是否超过最大重试次数 if conn.get("retry_count", 0) >= self.MAX_RETRIES: self.logger.warning(f"❌ 连接超过最大重试次数: {pile_code}") await self._close_single_connection(pile_code) continue if conn.get("isLogin") is True: real_active_count += 1 # 检查最后活动时间 last_activity = conn.get("last_time_stamp", 0) if current_time - last_activity > 60: # 1分钟无活动 self.logger.warning(f"桩号: {pile_code} 上次报文时间: {last_activity} 当前时间: {current_time} 时间间隔: {current_time - last_activity}") self.logger.warning(f"🕒 连接无活动超时: {pile_code}") connections_to_restart.append(pile_code) # 检查是否需要重启 if conn.get("needs_restart", False): connections_to_restart.append(pile_code) # 重启需要重置的连接 for pile_code in connections_to_restart: if pile_code in self.connections: conn = self.connections[pile_code] if conn['isLogin'] and conn['isLogin'] is not None: connections_to_restart.remove(pile_code) continue else: await self._close_single_connection(pile_code) # 重新启动工作协程 self.logger.info(f"🔄 重启连接: {pile_code}") task = asyncio.create_task( self.socket_worker(f"restart-{pile_code}", pile_code), name=f"restart_{pile_code}" ) self.batch_tasks.append(task) await asyncio.sleep(1) # 定期报告 restart_count = len(connections_to_restart) self.logger.info( f"🔍 健康检查: 活跃连接={real_active_count} 待重启={restart_count}" ) await asyncio.sleep(5) except Exception as e: self.logger.error(f"健康监控器异常: {e}") await asyncio.sleep(10) async def create_socket_connection_with_retry(self, message_id: str, pileCode: str, attempt: int) -> bool: """带重试机制的连接创建""" try: reader, writer = await asyncio.wait_for( asyncio.open_connection(self.server_config['ip'], self.server_config['port']), timeout=30.0 + min(attempt * 5, 30) # 随重试次数增加超时 ) async with self.connection_locks[pileCode]: if pileCode not in self.connections: self.connections[pileCode] = { 'reader': reader, 'writer': writer, 'pileCode': pileCode, 'message_id': message_id, 'retry_count': 0, 'last_heartbeat1': 0, 'last_heartbeat2': 0, 'last_time_stamp': 0, 'isLogin': False, 'timeout_count_login': 0, 'timeout_count': 0, 'heart_serialNum': "00 00", 'status': 'Offline', 'charging': False, 'priceModelList': [] } self.logger.info(f"连接成功: {message_id} 桩号: {pileCode}") return True except asyncio.TimeoutError: self.logger.warning(f"⛔ 连接超时: {message_id} 桩号: {pileCode} (尝试 #{attempt + 1})") if pileCode in self.connections: conn = self.connections[pileCode] if 'writer' in conn and conn['writer'] is not None: writer = conn['writer'] try: if not writer.is_closing(): writer.close() await writer.wait_closed() except Exception: pass if pileCode in self.connections: del self.connections[pileCode] await asyncio.sleep(1) # 短暂暂停 except ConnectionRefusedError: self.logger.warning(f"🚫 连接拒绝: {message_id} 桩号: {pileCode} (尝试 #{attempt + 1})") if pileCode in self.connections: conn = self.connections[pileCode] if 'writer' in conn and conn['writer'] is not None: writer = conn['writer'] try: if not writer.is_closing(): writer.close() await writer.wait_closed() except Exception: pass if pileCode in self.connections: del self.connections[pileCode] await asyncio.sleep(1) # 短暂暂停 except Exception as e: self.logger.error( f"❌连接错误: {message_id} 桩号: {pileCode} 错误: {e} (尝试 #{attempt + 1})") if pileCode in self.connections: conn = self.connections[pileCode] if 'writer' in conn and conn['writer'] is not None: writer = conn['writer'] try: if not writer.is_closing(): writer.close() await writer.wait_closed() except Exception: pass if pileCode in self.connections: del self.connections[pileCode] await asyncio.sleep(1) # 短暂暂停 return False async def start_reader_writer(self, message_id: str, pileCode: str): """启动读写任务""" if pileCode not in self.connections: return conn = self.connections[pileCode] reader = conn['reader'] writer = conn['writer'] self.writer, self.reader = AsyncSocketWriter(writer, pileCode, message_id, self.total, self.connections, self.connection_locks, self.logger), AsyncSocketReader( reader, pileCode, message_id, self.connections, self.connection_locks, self.logger) # 创建读写任务 read_task = asyncio.create_task( self.reader.start_reading(), name=f"reader_{pileCode}_{message_id}" ) write_task = asyncio.create_task( self.writer.start_write(), name=f"writer_{pileCode}_{message_id}" ) # 添加完成回调 read_task.add_done_callback(self.handle_task_completion) write_task.add_done_callback(self.handle_task_completion) # 添加到活跃任务集合 self._active_tasks.add(read_task) self._active_tasks.add(write_task) # 并行运行读写任务 try: await asyncio.gather( read_task, write_task, return_exceptions=True ) except Exception as e: self.logger.error(f"读写任务异常: {message_id} {pileCode}: {e}") 有无问题?
最新发布
11-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值