繁体   English   中英

为什么我不能在异步块中使用“使用”,在 F#

[英]Why can't I use 'use' in an async block, in F#

我有这个 function 从缓存中读取数据:

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
    }

兴趣线在这里:

使用 pBytes = 固定字节

它将无法编译:

“nativeptr<'a>”类型与“IDisposable”类型不兼容

但该行将编译为:

让 pBytes = 固定字节

这是在异步块中发生的。

这是为什么?

问题不在于use部分,而在于fixed部分。 fixed 关键字确保值保存在堆栈中。 将其与async结合使用的问题是计算表达式中使用的局部变量并不总是保存在堆栈中。 如果你有let! 在它们的使用之间,它们需要存储为 object 的字段,因此fixed不能在这种情况下工作。

您可以通过将固定变量的 scope 限制为非异步代码块来解决此问题:

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
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM