简体   繁体   English

如何正确延长 iOS 应用程序的后台时间,以便 HTTP 请求不会被取消?

[英]How can I properly extend the background time of an iOS app so that an HTTP request doesn't get cancelled?

I have an app (App1) that makes use of the WKWebView for a good portion of the UI.我有一个应用程序 (App1) 将WKWebView用于大部分 UI。 There is a scenario where an HTTP PUT request is sent from the WKWebView to a backend server to save some data.有这样一种场景,从WKWebView向后端服务器发送 HTTP PUT 请求以保存一些数据。 For this save operation to complete, the server will need approval thru another app (App2).要完成此保存操作,服务器将需要通过另一个应用程序 (App2) 的批准。 The user would normally switch to App2 to approve, then switch back to App1 to see the result of the save.用户通常会切换到 App2 进行批准,然后切换回 App1 以查看保存结果。 The problem is that when App1 gets backgrounded, it can cause the response to the save request to be cancelled, even though the save was completely successful on the backend server.问题是,当 App1 进入后台时,它可能会导致对保存请求的响应被取消,即使在后端服务器上保存完全成功。 There isn't any errors actually logged, but I'm fairly certain it is happening because iOS is killing the connection when the app gets suspended after it gets backgrounded.实际上没有记录任何错误,但我相当肯定它正在发生,因为 iOS 在应用程序在后台运行后暂停时正在终止连接。 I'm basing my thoughts on this discussion .我的想法是基于这个讨论

Since the time it takes to approve the save on App2 isn't that long, I figured I could just try to extend the background time of App1, and it appears to work in the times I've tested it.由于批准在 App2 上保存所需的时间并没有那么长,我想我可以尝试延长 App1 的后台时间,并且它似乎在我测试过的时间内有效。

However, I want to know if this is really the best strategy, and if so, are there any recommendations on my code (For example, should I move the BeginBackgroundTask inside of the Task.Run ):但是,我想知道这是否真的是最好的策略,如果是,对我的代码是否有任何建议(例如,我是否应该将BeginBackgroundTask Task.Run ):

I used these microsoft docs as an example.我以这些微软文档为例。

public override async void DidEnterBackground(UIApplication application)
{
    ExtendBackgroundTime(application);
}

private nint? webViewBgTaskId = null;
private CancellationTokenSource webViewBgTaskTokenSrc = null;

private void ExtendBackgroundTime(UIApplication application)
{
    // cancel the previous background task that was created in this function
    webViewBgTaskTokenSrc?.Cancel();
    webViewBgTaskTokenSrc = null;
    if (webViewBgTaskId.HasValue)
    {
        application.EndBackgroundTask(webViewBgTaskId.Value);
        webViewBgTaskId = null;
    }

    var cts = new CancellationTokenSource();
    nint taskId = default;
    taskId = application.BeginBackgroundTask(() =>
    {
        cts.Cancel();
        webViewBgTaskTokenSrc = null;
        application.EndBackgroundTask(taskId);
        webViewBgTaskId = null;
    });

    _ = Task.Run(async () =>
    {
        // For now, this is just set to 5 minutes, but in my experience,
        // the background task will never be allowed to continue for that long.
        // It's usually only about 30 seconds as of iOS 13.
        // But this at least gives it some finite upper bound.
        await Task.Delay(TimeSpan.FromMinutes(5), cts.Token);

        application.EndBackgroundTask(taskId);
        webViewBgTaskId = null;
    }, cts.Token);

    webViewBgTaskTokenSrc = cts;
    webViewBgTaskId = taskId;
}

The following code snippet demonstrates registering a task to run in the background:以下代码片段演示了注册要在后台运行的任务:

nint taskID = UIApplication.SharedApplication.BeginBackgroundTask( () => {});

//runs on main or background thread
FinishLongRunningTask(taskID);

UIApplication.SharedApplication.EndBackgroundTask(taskID);

The registration process pairs a task with a unique identifier, taskID , and then wraps it in matching BeginBackgroundTask and EndBackgroundTask calls.注册过程将任务与唯一标识符taskID ,然后将其包装在匹配的BeginBackgroundTaskEndBackgroundTask调用中。 To generate the identifier, we make a call to the BeginBackgroundTask method on the UIApplication object, and then start the long-running task, usually on a new thread.为了生成标识符,我们在UIApplication object 上调用 BeginBackgroundTask 方法,然后启动长时间运行的任务,通常在新线程上。 When the task is complete, we call EndBackgroundTask and pass in the same identifier.任务完成后,我们调用EndBackgroundTask并传入相同的标识符。 This is important because iOS will terminate the application if a BeginBackgroundTask call does not have a matching EndBackgroundTask .这很重要,因为如果BeginBackgroundTask调用没有匹配的EndBackgroundTask ,iOS 将终止应用程序。

Note : If you want to perform Tasks During DidEnterBackground method, these tasks must be invoked on a separate thread.注意:如果要在DidEnterBackground方法期间执行任务,则必须在单独的线程上调用这些任务。 Therefore, sample project uses Task to invoke FinishLongRunningTask .因此,示例项目使用 Task 来调用FinishLongRunningTask

Task.Factory.StartNew(() => FinishLongRunningTask(taskID));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 GET请求取消视频文件。 无法找到视频 - GET request for video files cancelled. Videos can't be found 延长 xamarin.ios 后台时间 - Extend background time on xamarin ios 如何在wpf桌面应用程序中加载背景中的照片,以便在图库中加载下一张照片不需要几秒钟? - How would I load photos in the background in a wpf desktop app so that it doesn't take a few seconds to load the next photo in the gallery? 如何在Linq2Sql应用程序中检查连接性,以便在失败时不会冻结? - How can I check the connectivity in a Linq2Sql app so it doesn't freeze if it fails? 如何正确发出 http web GET 请求 - How to properly make a http web GET request 我如何捕获异常,以免它破坏? - How can I catch the exception so it doesn't break? 我该如何解决,这样我的透明gif在Xamarin形式的iOS中不会显示黑色背景? - How can I solve so my transparent gif does not show a black background in Xamarin forms iOS? 如何从 HTTP 请求中获取 IP 地址和主机名? - How can I get the IP address and hostname from HTTP request? 如何获取最大http请求长度时间? - How to get the maximum http request length time? 我可以使用 Ocelot 将 POST http 请求重新路由到 GET http 请求吗? - Can I Reroute POST http request to a GET http request with Ocelot?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM