与async / await一起使用后台安全任务时的正确实现

时间:2014-12-22 16:31:25

标签: c# ios xamarin.ios xamarin async-await

如果用户按下主页按钮或正在打开应用程序切换器或正在接收来电,则当前正在运行的任务(Web请求)应在后台完成。我之前没有使用NSURLSession,因为我现在不想更改当前的基础课程。因此,我想使用background-safe tasks

我试过了:

public async Task retrieveCarList(){
    backgroundTaskID = UIApplication.SharedApplication.BeginBackgroundTask (() => {
        if(backgroundTaskID != 0){
            UIApplication.SharedApplication.EndBackgroundTask(backgroundTaskID);
            backgroundTaskID = 0;
        }
    });

    List<Car> carList = await manager.GetCarList();
    if(carList != null) {
        this.list = carList;
    } else {
        new UIAlertView("Error occurred", "", null, "OK", null).Show();
    }

    if(backgroundTaskID != 0){
        UIApplication.SharedApplication.EndBackgroundTask(backgroundTaskID);
        backgroundTaskID = 0;
    }
}

这似乎有效,但我必须对它进行更多测试。

问题

  1. 我可以在应用程序的任何地方使用BeginBackgroundTask / EndBackgroundTask吗?大多数examples仅在DidEnterBackground ...

  2. 中使用此功能
  3. 系统如何知道此后台线程的开头和结尾在哪里?

  4. 是否使用了BeginBackgroundTaskEndBackgroundTask之间的代码,甚至使用了与UI相关的内容?

  5. 这是博客帖子 Multitasking in iOS: the MonoTouch way – Part I: Pressing the Home button之后的正确实施,但是async / await

  6. 修改1:

    现在我尝试使用Console.WriteLine。似乎执行了await表达式,但之后的代码只会在用户再次打开应用程序时执行。我担心的是EndBackgroundTask只有在用户回到应用程序时才会执行。因此,如果未调用EndBackgroundTask,应用程序可能会被杀死。

    另一方面,如果我没有使用后台安全任务,则如果按下主页按钮,应用程序将不再在后台执行Web请求。所以它有点......

    如何将所有代码行放在await表达式中?然后所有代码都应该执行或?

    编辑2:

    await表达式置于System.Action之间会导致应用崩溃并且不会显示错误。我还尝试在 retrieveCarList()中使用BeginBackgroundTask并在等待的 GetCarList()中使用EndBackgroundTask,但代码仅在I&I执行时执行#39;回到应用程序中。另外,我尝试将await包装在另一个Task.Run中,但这会带来问题,因为我访问与UI相关的内容,而这种结构是不可能的。我的第一次尝试似乎仍然是最好的,但它具有上述缺点。如果有人有更好的实施,请发布。

1 个答案:

答案 0 :(得分:3)

<强>解决方案:

1。) Xamarin docs说我可以在任何地方使用此模式。这也在Apple docs中说明。

  

您可以在应用执行的任何时候调用此方法。

2。) Dimitris Tavlikos states

  

在BeginBackgroundTask调用之后,您的后台时间开始。

3。)根据Developing C# Apps for iPhone and iPad using MonoTouch: iOS Apps Development by Bryan Costanich,似乎暂停了UI线程。

4。)我的方法似乎运作正常。现在我将Console.WriteLine放在EndBackgroundTask之前,它就像它应该被调用一样!执行BeginBackgroundTaskEndBackgroundTask之间的所有内容。仅清除backgroundTaskID,但其他实施也不会这样做。