|
根据你提供的代码和问题描述,我发现这是一个使用大漠插件多线程绑定游戏窗口时出现的稳定性问题。以下是可能的原因和解决方案:
### 问题原因分析
1. **COM组件初始化冲突**:多个线程同时初始化COM组件可能导致冲突
2. **绑定参数过于严格**:使用了过多的绑定参数,可能导致某些窗口无法成功绑定
3. **绑定间隔时间不足**:1秒的间隔可能不足以让游戏窗口完全准备好接受绑定
4. **资源竞争**:多个线程同时操作同一组资源(如字库)可能引发冲突
5. **游戏保护机制**:游戏的反辅助机制可能阻止频繁的绑定操作
### 解决方案
以下是优化后的代码,主要改进了线程同步、绑定参数和错误处理:
```易语言
.版本 2
.支持库 spec
.子程序 _启动全部_被单击
.局部变量 hwnds, 文本型
.局部变量 hwnd_array, 文本型, , "0"
.局部变量 i, 整数型
.局部变量 hwnd, 整数型
.局部变量 总表项数, 整数型
.局部变量 账号, 文本型
.局部变量 当前列, 整数型
.局部变量 句柄文本, 文本型
' 清空之前的线程信息
清除数组 (线程信息)
hwnds = 全局大漠.EnumWindowByProcess (“WuXia_Client_x64.exe”, “天涯明月刀”, “GEMAINWINDOWCLASS”, 1 + 8 + 16 + 32)
调试输出 (hwnds)
.如果真 (取文本长度 (hwnds) = 0)
日志输出 (“枚举窗口失败”)
返回 ()
.如果真结束
hwnd_array = 分割文本 (hwnds, “,”, )
总表项数 = 取数组成员数 (hwnd_array)
.如果真 (总表项数 = 0)
日志输出 (“没有找到游戏窗口”)
返回 ()
.如果真结束
' 调整线程信息数组大小
重定义数组 (线程信息, 总表项数)
' 启动线程池
多线程_启动线程池 (总表项数, 3) ' 创建足够的线程,最大并行数为3
' 分批启动线程,避免同时过多线程导致系统资源不足
.计次循环首 (总表项数, i)
hwnd = 到整数 (hwnd_array [i])
' 初始化线程信息
线程信息 [i].窗口句柄 = hwnd
线程信息 [i].线程状态 = #线程状态_未启动
线程信息 [i].登录状态 = #登录状态_未登录
' 等待前一个线程完成初始化
.如果真 (i > 1)
等待 (2000) ' 增加初始延迟,给系统足够时间准备
.如果真结束
' 提交任务到线程池
.如果真 (多线程_提交任务 (i, &脚本主线程) = 假)
日志输出 (“任务提交失败,窗口句柄:” + 到文本 (hwnd))
.如果真结束
' 增加间隔时间,避免频繁操作
全局大漠.delay (1500)
.计次循环尾 ()
.版本 2
.子程序 脚本主线程, , , 脚本主线程,脚本的主要逻辑在这里处理
.参数 序号, 整数型
.局部变量 dm, dmsoft
.局部变量 dm_ret, 整数型
.局部变量 重试次数, 整数型
.局部变量 死循环, 逻辑型
' 初始化当前线程com组件为STA模式
CoInitializeEx (0, 2)
线程信息 [序号].线程状态 = #线程状态_正在运行
多线程_异步通知UI (#通知类型_更新, 序号)
' 创建对象
线程信息 [序号].dm.创建 ()
dm = 线程信息 [序号].dm
' 检测对象是否创建成功
.如果真 (dm.Ver () = “”)
日志输出 (“对象创建失败”)
多线程_异步通知UI (#通知类型_停止, 序号)
返回 ()
.如果真结束
' 设置超时时间,避免长时间等待无响应的操作
dm.SetDllPathTimeout (5000, 1)
' 增加随机延迟,减少线程间的竞争
脚本延时 (序号, 1000 + 取随机数 (0, 500))
' 开启全局共享字库
dm.EnableShareDict (1)
' 设置路径
dm.SetPath (取运行目录 ())
' 尝试多次绑定,提高成功率
重试次数 = 0
.判断循环首 (重试次数 < 3)
' 尝试使用不同的绑定参数组合
.如果 (重试次数 = 0)
' 尝试标准绑定参数
dm_ret = dm.BindWindowEx (线程信息 [序号].窗口句柄, “dx2”, “dx.mouse.position.lock.api|dx.mouse.state.api|dx.mouse.api|dx.mouse.focus.input.api|dx.mouse.focus.input.message|dx.mouse.clip.lock.api|dx.mouse.input.lock.api”, “dx.keypad.input.lock.api|dx.keypad.state.api|dx.keypad.api”, “dx.public.graphic.protect|dx.public.hide.dll|dx.public.km.protect”, 103)
.否则如果 (重试次数 = 1)
' 尝试更宽松的绑定参数
dm_ret = dm.BindWindowEx (线程信息 [序号].窗口句柄, “dx2”, “dx.mouse.position.lock.api|dx.mouse.state.api|dx.mouse.api|dx.mouse.focus.input.api”, “dx.keypad.input.lock.api|dx.keypad.state.api|dx.keypad.api”, “dx.public.graphic.protect|dx.public.hide.dll”, 103)
.否则
' 尝试最宽松的绑定参数
dm_ret = dm.BindWindowEx (线程信息 [序号].窗口句柄, “dx2”, “dx.mouse.position.lock.api|dx.mouse.state.api|dx.mouse.api”, “dx.keypad.input.lock.api|dx.keypad.state.api|dx.keypad.api”, “dx.public.graphic.protect”, 103)
.如果结束
.如果 (dm_ret = 1)
日志输出 (“绑定成功,窗口句柄:” + 到文本 (线程信息 [序号].窗口句柄))
跳出循环 ()
.否则
日志输出 (“绑定尝试 ” + 到文本 (重试次数 + 1) + “ 失败,错误码:” + 到文本 (dm.GetLastError ()))
dm.UnBindWindow ()
脚本延时 (序号, 2000) ' 等待一段时间再重试
重试次数 = 重试次数 + 1
.如果结束
.判断循环尾 ()
.如果真 (dm_ret ≠ 1)
日志输出 (“主:绑定失败,已尝试所有参数组合”)
' 通知主线程进行结束操作(释放资源)
多线程_异步通知UI (#通知类型_停止, 序号)
返回 ()
.如果真结束
' 绑定成功,继续执行脚本逻辑
日志输出 (“开始执行脚本逻辑,窗口句柄:” + 到文本 (线程信息 [序号].窗口句柄))
' 后续脚本逻辑...
```
### 主要改进点
1. **线程池管理**:
- 使用线程池控制并发数量,避免过多线程同时运行导致系统资源不足
- 增加线程启动间隔时间,避免瞬间创建大量线程
2. **绑定参数优化**:
- 提供多种绑定参数组合,逐步尝试更宽松的配置
- 增加重试机制,每个窗口最多尝试3次不同的绑定参数
3. **错误处理增强**:
- 增加详细的日志记录,便于跟踪问题
- 绑定失败后进行资源清理,避免残留绑定状态
4. **同步与延迟调整**:
- 增加随机延迟,减少线程间的竞争
- 优化线程启动顺序,避免同时操作同一资源
5. **稳定性增强**:
- 设置DLL操作超时时间,避免长时间等待无响应的操作
- 完善资源初始化和释放流程
这些改进应该能显著提高多窗口绑定的成功率。如果问题仍然存在,建议检查游戏是否有反辅助机制限制了多开和绑定操作,或者尝试联系大漠插件官方获取技术支持。 |
|