队列读取器代理 遇到错误 Row handle is invalid

本文介绍了解决在数据库发布中更改表名称后导致的队列读取器错误的方法。通过删除堵塞队列和相关触发器等步骤,确保订阅数据库不再受原表影响。

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


今天测试在发布中更改表名称,在发布数据库更改后重新发布这个表。
但是原来的表在订阅没有删除,不小心插入数据到原表中,队列读取器停止并报错。






队列读取器代理在连接“HZC”上的“DBname”时遇到错误“Row handle is invalid.”。
请确保正确定义了分发和订阅,并确保这两台服务器都在运行。 


队列应用到发布服务器失败,原因是在发布数据库中找不到表对象


解决办法:



--先在订阅数据库把堵塞的队列删除
SELECT *  FROM [dbo].[MSrepl_queuedtraninfo] (NOLOCK)order by maxorderkey asc

DELETE FROM [dbo].[MSrepl_queuedtraninfo] WHERE tranid='Ha;.ha7`Q1K<N4PVbKTgD=5---/XHM--'
DELETE FROM [dbo].[MSreplication_queue]   WHERE tranid='Ha;.ha7`Q1K<N4PVbKTgD=5---/XHM--'


执行后队列读取器会回到正常状态。
接下来为了确保队列不受原来的订阅表影响,删除原来的【触发器】即可。

DROP TRIGGER trg_MSsync_del_Tab,trg_MSsync_ins_Tab,trg_MSsync_upd_Tab

--也可以把没有的数据和对象从订阅库中删除!
DROP PROCEDURE sp_MSdel_dboTab,sp_MSins_dboTab,sp_MSupd_dboTab

DELETE FROM dbo.MSreplication_objects WHERE article='Tab'

DELETE FROM dbo.MSsubscription_articles WHERE article='Tab'

DELETE FROM dbo.MSsubscription_articlecolumns 
WHERE artid IN(SELECT artid FROM dbo.MSsubscription_articles WHERE article='Tab')


原来的订阅数据库的这个表【Tab】就不影响发布了,可删除或保留。





我在单片机用无线串口发送数据,每隔20ms连续9ms发送413个字节的数据,电脑vs通过windows库配置api接受串口传来的数据,但延迟太高,帮我优化图像加数据 vector<unsigned char> serialBuffer; const vector<unsigned char> FRAME_HEADER = { 0xAA, 0 x02, 0 x40, 0 x08, 0xC8, 0 x00, 0 x02, 0 x00 }; const vector<unsigned char> uint8 mx[120][188] = { 0 };// 从缓冲区中查找并处理一帧图像 bool processFrameFromBuffer(Mat &image) { size_t bufferSize = serialBuffer.size(); size_t headerSize = FRAME_HEADER.size(); size_t frameSize = headerSize + 400; // 帧头长度 + 400个数据字节 // 1. 在缓冲区中查找完整帧头 size_t headerPos = 0; for (size_t i = 0; i < bufferSize; i++) { if (serialBuffer[i] == FRAME_HEADER[headerPos]) { headerPos++; if (headerPos == headerSize) { // 找到完整帧头 // 2. 检查是否有足够数据组成一帧 if (bufferSize >= i + 1 + frameSize) { [图片 252.png] // 3. 提取坐标数据 memset(mx, 0, sizeof(mx)); const unsigned char* dataPtr = &serialBuffer[i + 1 + 5]; for (int k = 0; k < 400; k += 2) { if (k + 1 < 400) { uint8 x = dataPtr[k]; uint8 y = dataPtr[k + 1]; if (x < IMAGE_WIDTH && y < IMAGE_HEIGHT) { mx[y][x] = 255; // 注意坐标顺序:mx[行][列] = mx[y][x] } } } if(serialBuffer[i]=DATAHEADER){ value=serialBuffer[i+1]+serialBuffer[i+2] 处理int16, continue; } // 4. 转换为图像 for (int row = 0; row < IMAGE_HEIGHT; row++) { unsigned char* ptr = image.ptr<uchar>(row); for (int col = 0; col < IMAGE_WIDTH; col++) { ptr[col] = mx[row][col]; } } // 5. 从缓冲区中移除已处理的数据 serialBuffer.erase(serialBuffer.begin(), serialBuffer.begin() + i + 1 + frameSize); return true; } else { // 数据不足,等待后续数据 break; } } } else { headerPos = 0; // 重置匹配 } } return false; } // 优化后的图像读取函数(带缓存机制) bool readImageFromSerial(HANDLE hPort, Mat &image) { const int BUFFER_CHUNK = 512; // 每次读取的字节数 vector<unsigned char> readBuffer(BUFFER_CHUNK); DWORD bytesRead = 0; // 1. 非阻塞读取串口数据(设置超时为0) COMMTIMEOUTS timeouts; GetCommTimeouts(hPort, &timeouts); timeouts.ReadIntervalTimeout = MAXDWORD; // 字节间超时设为最大值 timeouts.ReadTotalTimeoutConstant = 100; timeouts.ReadTotalTimeoutMultiplier = 100; SetCommTimeouts(hPort, &timeouts); // 2. 读取数据并添加到缓存 if (ReadFile(hPort, readBuffer.data(), BUFFER_CHUNK, &bytesRead, NULL) && bytesRead > 0) { serialBuffer.insert(serialBuffer.end(), readBuffer.begin(), readBuffer.begin() + bytesRead); } // 3. 处理缓冲区中的帧 return processFrameFromBuffer(image); }
最新发布
07-01
### 解决 'Handle Is Invalid' 错误 当尝试获取设备版本信息时遇到 "handle is invalid" 的错误通常意味着程序试图访问一个未初始化或已关闭的句柄。这可能是由于多种原因引起的,包括但不限于: - 连接尚未建立成功即尝试读取数据。 - 使用了一个已经断开连接的设备句柄。 - 句柄对象在调用期间被意外销毁。 为了处理这个问题,建议采取以下措施来确保稳定性和可靠性[^1]: #### 验证连接状态 确认应用程序与目标设备之间的蓝牙连接确实存在,并且处于活动状态之前再执行任何操作请求。可以实现心跳检测机制定期验证链路质量。 ```csharp if (device.Connected) { // 安全地继续下一步骤... } else { Console.WriteLine("Device connection lost."); } ``` #### 检查服务和特征的有效性 确保所使用的GATT服务和服务中的特性已经被正确发现并且有效。对于某些特定类型的硬件,在首次配对之后可能需要额外的时间让所有必要的属性变得可用。 ```python for service in gatt_services: if service.uuid == target_service_uuid: for characteristic in service.characteristics: if characteristic.uuid == version_info_characteristic_uuid: try: value = await client.read_gatt_char(characteristic) print(f"Version Info: {value.decode()}") except Exception as e: logging.error(e) ``` #### 处理异常情况下的重试逻辑 引入合理的超时设置以及有限次数内的自动重试策略可以帮助应对临时性的网络波动或其他瞬态故障条件。 ```javascript async function fetchDeviceInfoWithRetry(retries=3){ let attempt = 0; while(attempt < retries){ try { const info = await getDeviceInformation(); return info; } catch(error) { console.log(`Attempt ${attempt} failed.`); ++attempt; await sleep(500); // Wait before retrying. } } throw new Error('Max attempts reached'); } ``` 通过上述方法能够有效地减少因无效句柄而导致的操作失败概率,提高系统的健壮性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值