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是两种非常不同的结构,具有非常不同的语义,从一个结构到另一个结构的经验不容易传递
异步等待是链接任务的一种方式。Atask谢谢,我就是这么想的。我在很多地方使用这种模式。除了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