我有这个函数可以从缓存中读取数据:
let private tryLoadFromCacheAsync filename =
async {
let filespec = makePath filename
match File.Exists filespec with
| true ->
let! bytes = File.ReadAllBytesAsync(filespec) |> Async.AwaitTask
use pBytes = fixed bytes
let sourceSpan = Span<byte>(NativePtr.toVoidPtr pBytes, bytes.Length)
return Some (MemoryMarshal.Cast<byte, ShortTradeData>(sourceSpan).ToArray())
| false ->
return None
}
感兴趣的线路在这里:
use pBytes = fixed bytes
它将无法编译:
The type 'nativeptr<'a>' is not compatible with the type 'IDisposable'
但是该行将编译为:
let pBytes = fixed bytes
这发生在异步 block 中。
这是为什么?
最佳答案
问题较少与use
部分有关,而更多与fixed
部分有关。 fixed 关键字确保值保留在堆栈中。将其与异步结合的问题是计算表达式中使用的局部变量并不总是保留在堆栈上。如果您在使用它们之间使用了 let!
,则它们需要存储为对象的字段,因此 fixed
无法在此类上下文中工作。
您可以通过将固定变量的范围限制为非异步代码块来解决此问题:
let private tryLoadFromCacheAsync filename =
async {
let filespec = makePath filename
match File.Exists filespec with
| true ->
let! bytes = File.ReadAllBytesAsync(filespec) |> Async.AwaitTask
let res =
use pBytes = fixed bytes
let sourceSpan = Span<byte>(NativePtr.toVoidPtr pBytes, bytes.Length)
MemoryMarshal.Cast<byte, ShortTradeData>(sourceSpan).ToArray()
return Some res
| false ->
return None
}
关于f# - 为什么我不能在 F# 的异步 block 中使用 'use',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71790058/