运行以下代码时,出现Cannot access a disposed object
错误(MyClient
是由C#项目中的服务引用生成的WCF客户端)。
type Action =
| Add
| Update
let addStuff (myClient:MyClient) arg = async {
let! response = myClient.AddAsync arg |> Async.AwaitTask
return response.ID
}
let updateStuff (myClient:MyClient) arg = async {
let! response = myClient.UpdateAsync arg |> Async.AwaitTask
return response.ID
}
let doStuff arg =
use myClient = new MyClient()
match arg.Action with
| Add -> arg |> addStuff myClient
| Update -> arg |> updateStuff myClient
let args = [Add, Add, Update, Add]
let results =
args
|> List.map doStuff
|> Async.Parallel
看来客户正在被我预料之中。如果我将
doStuff
更改为:let doStuff arg = async {
use myClient = new MyClient()
return!
match arg.Action with
| Add -> arg |> addStuff myClient
| Update -> arg |> updateStuff myClient
}
这两个函数的返回类型均为
Async<int>
。为什么在第一个示例中较早处置客户?我认为两个示例在逻辑上都是相同的。我的理解是,仅当需要使用async
绑定时,才需要!
工作流程,在这种情况下,我认为这是不必要的,因为特定功能中实际正在等待。 最佳答案
问题出在doStuff
上:
let doStuff arg =
use myClient = new MyClient()
match arg.Action with
| Add -> arg |> addStuff myClient
| Update -> arg |> updateStuff myClient
您正在将
myClient
传递给捕获MyClient
实例的异步函数。但是,当doStuff
返回时,它将在Dispose
实例上调用MyClient
并处理客户端。当您的异步方法开始运行时,它使用的是已处置实例。使
doStuff
起作用是因为处理成为异步工作流的一部分。另一个选择是不
use
MyClient
实例,而instean让addStuff
和updateStuff
创建自己的MyClient
实例。