Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wcf 在F#中使用IDisposable时是否需要使用async关键字?_Wcf_F#_Async Await_Idisposable - Fatal编程技术网

Wcf 在F#中使用IDisposable时是否需要使用async关键字?

Wcf 在F#中使用IDisposable时是否需要使用async关键字?,wcf,f#,async-await,idisposable,Wcf,F#,Async Await,Idisposable,运行以下代码时,我收到一个无法访问已处理对象错误(MyClient是由C#项目中的服务引用生成的WCF客户端) 客户似乎在我预期之前就被处置了。如果我将doStuff更改为: let doStuff arg = async { use myClient = new MyClient() return! match arg.Action with | Add -> arg |> addStuff myClient | Up

运行以下代码时,我收到一个
无法访问已处理对象
错误(
MyClient
是由C#项目中的服务引用生成的WCF客户端)

客户似乎在我预期之前就被处置了。如果我将
doStuff
更改为:

let doStuff arg = async {
    use myClient = new MyClient()
    return!
        match arg.Action with
        | Add -> arg |> addStuff myClient
        | Update -> arg |> updateStuff myClient
}

这两个函数的返回类型都是
Async
。在第一个示例中,为什么要在早期处置客户机?我认为这两个例子在逻辑上是相同的。我的理解是,只有在需要使用
时才需要
异步
工作流绑定是不必要的,因为实际等待发生在特定函数中。

问题在于
doStuff

let doStuff arg =
    use myClient = new MyClient()
    match arg.Action with
    | Add -> arg |> addStuff myClient
    | Update -> arg |> updateStuff myClient
您正在将
myClient
传递到一个异步函数中,该函数捕获
myClient
实例。但是,当
doStuff
返回时,它调用
MyClient
实例上的
Dispose
,并处理客户端。当异步方法开始运行时,它使用的是一个已释放的实例

制作
doStuff
之所以有效,是因为dispose已成为异步工作流的一部分


另一种选择是不使用
MyClient
实例,而是使用
addStuff
updateStuff
创建自己的
MyClient
实例。

在这种情况下
异步{…}
块给您的是两件事:

  • 它会延迟其中所有代码的执行,直到执行异步计算
  • 它相应地处理
    use
    关键字(即,在嵌套的
    addStuff
    /
    updateStuff
    工作流执行后,IDisposable将被释放)
  • 至于你使用的模式是否错误——是的,是的

    F#async和C#async await是两种非常不同的结构,具有非常不同的语义,从一个结构到另一个结构的经验不容易传递


    异步等待是链接
    任务的一种方式。A
    task谢谢,我就是这么想的。我在很多地方使用这种模式。除了
    IDisposable
    ,这个模式还有什么问题吗?我认为这只是一个问题,因为一旦超出词法范围,它就会处理
    myClient
    。对于任何其他POCO或记录,这都不重要。看起来像是Resharper analysis中的
    已处置的闭包访问
    案例。谢谢。我想这意味着我使用的模式应该只在您不关心早期代码是否立即运行的情况下执行(这是一个奇怪的用例)。我同意这一点。
    let doStuff arg =
        use myClient = new MyClient()
        match arg.Action with
        | Add -> arg |> addStuff myClient
        | Update -> arg |> updateStuff myClient
    
    let doStuff arg =
        use myClient = new MyClient()
        match arg.Action with
        | Add -> arg |> addStuff myClient
        | Update -> arg |> updateStuff myClient