2017-11-10 214 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