2017-11-10 213 views
3

我需要在後臺調用一個調用web服務的API。我不希望將(非常複雜的)方法變成異步,只是說「在後臺執行所有操作」。在F#中如何在後臺運行阻塞調用?

但我失去了如何與F#這一點。這是我有:

  let task = async { 
       let result = SyncApi.syncData(login.url, login.zone, login.user, login.pwd) <-- THIS MUST RUN IN BACKGROUND... 
       match result with 
       |Some(msg) -> failwith msg 
       | None ->() 
      } 

      task 
      |> Async.Catch 
      |> Async.RunSynchronously 
      |> fun x -> 
        match x with 
        | Choice1Of2 x -> rootPage.Navigation.PopToRootAsync(true) |> ignore 
        | Choice2Of2 ex -> showMsgError(ex.Message) 

回答

3

如果您正在尋找簡單的射後不理的風格,開始調用API時不要使用當前線程的結果,Async.Start(task)可能是你在找什麼。它需要Async工作流程,在線程池中啓動它並立即返回,以便您的方法可以繼續。

但看到您需要結果來更改導航或顯示錯誤消息,您可能需要在當前線程上同步調用SyncApi並等待其結果。

另外,如果您的應用程序模型允許的話,你可以這樣做:

(* Define the task including error handling. *) 
let task = async { 
    let result = SyncApi.syncData(login.url, login.zone, login.user, login.pwd) 
    match result with 
    | Some msg -> 
     (* This may have to be posted back to the UI context. 
      Correct way depends on technology (Xamarin vs. WPF vs. MVC...) *) 
     showMsgError msg 
    | None ->() 
} 

(* Fire and forget the async API call. *) 
Async.Start(task) 

(* Optimistically navigate away immediately, 
    while `task` may still be in progress. *) 
rootPage.Navigation.PopToRootAsync(true) |> ignore 

這將啓動一個線程池的任務,導航離開,但如果異步任務失敗,它會觸發錯誤消息。但是,它假定您的應用程序可以異步顯示錯誤消息,例如作爲彈出窗口,而不僅僅是在啓動任務的頁面的上下文中。

+0

不,我不能忽略錯誤並離開。 – mamcx

+0

爲什麼你需要*首先在背景上調用API?如果要在處理期間使UI響應,但不能異步顯示錯誤消息,恐怕除了讓整個方法異步外,別無他法。如果您想使該方法更快,那麼顯示錯誤的同步點就是問題 - 它不會消失,它必須等待處理結果。 –

+0

是的是讓UI響應。在swift中很容易做到這一點,我只是安排在另一個線程的任務︰https://stackoverflow.com/questions/24056205/how-to-use-background-thread-in-swift – mamcx