我的目标是
我使用带有以下
的viewmodel准备了第一个演示代码member this.RunSetStatus() =
async {
this.Status <- "!Start resetting @" + DateTime.Now.ToString "yy.MM.dd hh:mm:ss"
let! task = async {
do! Async.Sleep (10 * 1000)
return "!Reset done @" + DateTime.Now.ToString "yy.MM.dd hh:mm:ss"
}
this.Status <- task
} |> Async.StartImmediate
它表现得如预期所以我对上述情况感到满意。 问题是我在演示中使用真正的阻塞工作替换Sleep,就像wcf使用者一样,检索一些结果。
member this.CheckReport(user : string) =
async {
let endpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof<IClaimService>),
new BasicHttpBinding(),
new EndpointAddress(address))
let factory = new ChannelFactory<IClaimService>(endpoint)
let channel = factory.CreateChannel()
let resp = channel.CheckReport(user)
factory.Close()
return resp
}
从我的最终委托命令
调用let RefreshLogic() =
this.RefreshIsActive <- true
async {
let cons = ConsumerLib.ConsumerWCF()
let! task, msg = async {
try
let! resp = cons.CheckReport(Environment.UserName.ToLower())
return resp , ""
with
|exc -> return [||], (ConsumerLib.FindInner(exc).Message + ConsumerLib.FindInner(exc).StackTrace)
}
this.Reports <- task
this.RefreshIsActive <- false
this.StatusMsg <- msg
this.ExportCommand.RaiseCanExecuteChanged()
} |> Async.StartImmediate
不幸的是,它在刷新时冻结了GUI(为什么?)
答案 0 :(得分:1)
问题在于您的CheckReport
功能。虽然它是一个异步块,但它实际上从不调用任何异步工作(即:没有任何内容通过let!
或do!
绑定),因此整个块同步运行。
即使工作在异步工作流内部,当您使用StartImmediate
时,工作也会同步运行到第一个实际的异步函数调用,该调用将受let!
或{{1 }}。由于您的工作是完全同步的,因此这会向上传播,最终会同步,阻止UI。
如果你的WCF绑定被设置为包含Task返回的异步版本,那么这里最好的方法是使用WCF方法的异步版本,它看起来像:
do!