F#asyncio;在同一个线程中运行异步表达式,但能够等待异步操作(例如do!)

时间:2014-07-04 16:27:03

标签: f# f#-async

使用F#async试验一些我告诉我,我可以在当前运行的线程上启动。这似乎允许我运行一个异步表达式,它仍然可以传递控制,每当进入某个异步操作(例如do!)时,都会异步到async表达式之外的代码。请参阅下面的简单示例:

open System.Threading

let workThenWait() = async { 
  printfn "async start"
  do! Async.Sleep(1000) 
  printfn "async end"
  }

let demo() = 
  workThenWait() |> Async.StartImmediate
  printfn "main started"
  // here I want to wait to the async expression in case it has passed control
  printfn "main end"

demo()

我们得到的结果是:

async start
main started
main end
async end

另一方面,如果我使用 StartAsTask (在演示中)执行相同的异步表达式(在本例中为workThenWait),我可能会等待结束。

我的问题是:

使用前面的示例使用StartImmediate,我可以在同一个线程上运行,但是如果调用了一些异步操作(例如do!)并且向前传递控制权,那么还要等到异步表达式的末尾吗?

2 个答案:

答案 0 :(得分:2)

我认为您需要Async.RunSynchronouslyhttp://msdn.microsoft.com/en-us/library/ee370262.aspx

更新: 好的,现在我更了解你想要什么,我能用Async.StartWithContinuations方法实现这个目标。

以下是代码:

open System.Threading
let f() =
printfn "main thread: %A" Thread.CurrentThread.ManagedThreadId
let c1 = 
    async {
            printfn "c1 async thread: %A" Thread.CurrentThread.ManagedThreadId
            do! Async.Sleep(1000) 
            return "some result"
          }

let continuation s = 
    printfn "continuation thread: %A" Thread.CurrentThread.ManagedThreadId
    printfn "now the code You want after waiting and the result %s" s

Async.StartWithContinuations( 
    c1, 
    continuation,
    (fun _ -> ()), 
    (fun _ -> ())
    )

printfn "Code that runs during async computation"

现在这绝对不是很易读,因为代码流不明显。我找不到更好的解决方案。

答案 1 :(得分:1)

您可以使用Hopac libary:

执行此操作
let workThenWait() = job { 
  printfn "async start"
  do! Hopac.Timer.Global.sleep (TimeSpan.FromMilliseconds 1000.) 
  printfn "async end"
  }

let demo() = 
  let promise = workThenWait() |> Promise.start |> run
  printfn "main started"
  // here I want to wait to the async expression in case it has passed control
  let result = run promise
  printfn "main end"

demo()

Hopac比async更具性能和功能,与它的优点相比鲜为人知。我强烈推荐它。