You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

F#读取Dualshock4时FileStream.ReadAsync失败但同步Read可正常运行

问题原因
  • FileStream异步模式未显式启用:虽然调用File.OpenHandle时指定了FileOptions.Asynchronous,但使用FileStream(SafeFileHandle, FileAccess)重载构造实例时,默认useAsync参数为false,此时FileStream会用同步IO逻辑模拟异步操作,针对HID这类非磁盘类特殊字符设备时,会触发Windows内核层的参数校验错误。
  • 缓冲策略适配缺陷:.NET6默认的BufferedFileStreamStrategy对非可寻的字符设备异步读取的兼容性存在问题,内部缓冲逻辑会额外修改IO请求参数,导致HID驱动拒绝请求,你遇到的报错堆栈中的BufferedFileStreamStrategy.<ReadFromNonSeekableAsync>d__38.MoveNext()也印证了这一点。
修复方案

修改FileStream构造逻辑,显式启用异步模式、禁用内部缓冲即可,修正后的完整代码如下:

module Example =
  let ds4ReadBufSize = 64

  let read device =
    let buffer = Array.zeroCreate ds4ReadBufSize
    async {
      use file = File.OpenHandle(device, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, FileOptions.Asynchronous ||| FileOptions.SequentialScan)
      // 显式指定禁用内部缓冲、启用异步模式
      use fileStream = new FileStream(file, FileAccess.Read, bufferSize: 0, useAsync: true)
      let! d = fileStream.ReadAsync(buffer, 0, buffer.Length) |> Async.AwaitTask
      printfn "%d" d // 同时修正原代码的变量名笔误,原代码错误引用了未定义的read变量
    }

如果修改后仍有异常,可以移除File.OpenHandle参数中的FileOptions.SequentialScan,该参数是针对磁盘文件顺序读取做的优化,对HID设备没有实际作用,反而可能干扰IO请求参数。

补充说明:如果后续适配其他HID设备,建议先调用Windows HID原生API获取设备的实际输入报告长度作为缓冲区大小,避免因缓冲区长度不匹配触发同类参数错误。

内容的提问来源于stack exchange,提问作者Aldo Stracquadanio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 02:06:01