0

我在玩 Funscript,想从我的工作流程中得到一些结果。我将那些天真的定义(没有结果单元格)添加到 Async 模块中。

   static member RunSynchronously(workflow:Async<'T>, ?timeout:int,?cancellationToken:CancellationToken) =
      let result = ref None
      let token = defaultArg cancellationToken { Cell = None }
      let (Cont f) = workflow
      let aux = { StackCounter = ref 0; ExceptionCont = ignore; 
                  CancelledCont = ignore; CancellationToken = token }
      f { Cont = (fun v -> result :=  Some v); Aux = aux }
      let r = !result
      r.Value

   static member StartChild(computation:Async<'T>,?millisecondsTimeout:int) = 
      async { return Async.FromContinuations(fun (cont, econt,ccnt) -> cont (Async.RunSynchronously computation))           }

在这种情况下有效

   let test =  async{  let t = async { let! r = async { return "inside" }
                                       return "Hello" } 
                       let! task = Async.StartChild t
                       let! res = task
                       return res   
                    } |> Async.RunSynchronously 

但是当被问及“真正”使用时会摔倒

  let toto = Globals.document.createElement_img()
   toto.id <- "toto"
   Globals.document.body.appendChild(toto :> Node) |> ignore
   let test =  async{  let t = async { let! r = Async.AwaitJQueryEvent(j?toto.load)
                                       return "Hello" } 
                       let! task = Async.StartChild t
                       do toto.src <- "redundant.png"
                       let! res = task
                       return res   
                    } |> Async.RunSynchronously 

因为 j?toto.load 方法不会暂停并给我回电,并且会中断异步流程。我想这就是使用单线程 javascript 所做的事情。

什么是真正的解决方案?像在 F# 中那样实施暂停是唯一的方法吗?

4

1 回答 1

3

异步工作流的 FunScript 实现不使用当今 JS 中可能提供的任何高级线程机制。它只是在主浏览器线程上运行所有东西——这也是它只提供映射的Async.StartImmediate原因,因为这在逻辑上对应于标准 F# 运行时中的这种行为。

如果你想启动一个等待事件然后同步运行的工作流,那么这在这个模型中是不可能的——所以你不能合理地实现RunSynchronously它总是有效的(要同步运行,你需要阻塞当前线程,但是你不能等待事件......)

所以,我认为你需要以某种方式重组你的代码,这样它就不需要同步等待——可能也让调用者异步。

于 2013-10-28T00:15:49.503 回答