为了账号安全,请及时绑定邮箱和手机立即绑定

HttpClient 未在最小化的 UWP 应用程序中执行 GetAsync

HttpClient 未在最小化的 UWP 应用程序中执行 GetAsync

C#
人到中年有点甜 2021-11-21 10:06:56
我正在做一个播放几个视频的项目。为了能够播放这些视频,我需要在应用程序通过HttpClientfrom请求时获取它们的数据System.Net.Http。一切正常,当应用程序处于前台时,UWP 应用程序会从 Internet 下载所需的信息。一旦应用程序离开前台并被用户最小化HttpClient,无论是来自命名空间System.Net.Http还是Windows.Web.Http命名空间,都不起作用。我什至试图在那里设置一个断点,一旦我继续前进HttpClient就不会响应该await client.GetAsync()方法并停留在那里而不返回任何结果,除非您再次激活该应用程序然后它返回任何值。我无法使用,BackgroundTasks因为他们需要,Triggers但我需要按需访问数据。我也读过这篇文章,描述了请求,ExtendedExecutionState但结果还是一样。当应用程序收到播放项目列表的请求时,我会请求此状态。即使在获得结果为 之后Allowed,HttpClient也具有与上述相同的行为。有没有什么方法可以在请求时执行互联网相关查询并获取一些信息?我执行从互联网访问数据的代码是:public static async Task<string> GetResponseDataFromAPI(string apiRequestUrl, CancellationTokenSource cts = default){    cts = cts ?? new CancellationTokenSource(TimeSpan.FromSeconds(20));    try    {        var responseData = await AuthRequestHelper.globalHttpClient.GetAsync(apiRequestUrl, cts.Token);        var result = await responseData.Content.ReadAsStringAsync();        return result;    }    catch (Exception ex)    {        INotifyHelper.iNotifyObject.IsVideoLoading = false;        INotifyHelper.iNotifyObject.IsDataLoading = false;        // show error        return "{ \"error\": {\"code\": " + $"\"{ex.HResult}\", \"message\": \"{ex.Message}\"" + "} }";    }}然后分析返回的值以从中获取所需的数据。执行请求的代码ExtendedExecutionSession是:public static async void RequestBackgroundExtendedExecution(){    using (var session = new ExtendedExecutionSession())    {        session.Reason = ExtendedExecutionReason.Unspecified;        session.Description = "Background Playlist Playback";        session.Revoked += Session_Revoked;        if (await session.RequestExtensionAsync() is ExtendedExecutionResult result)        {            if (result == ExtendedExecutionResult.Denied)            {                // show user that background playlist playback will not be possible            }        }    }}在最小化状态下,是否可以执行任何操作来执行请求的操作?指向正确方向的一点帮助将不胜感激。谢谢
查看完整描述

2 回答

?
幕布斯7119047

TA贡献1794条经验 获得超8个赞

的BackgroundTransfer类专门在后台下载数据设计,即使应用程序已被暂停或关闭。

HttpClient 更适合快速完成的非常短的下载。对于像视频这样的冗长下载,请使用Windows.Networking.BackgroundTransfer.BackgroundDownloader。如果您需要在下载完成时处理文件,您可以使用该完成作为后台任务的触发器。

有关概述和操作方法,请参阅提供的文档链接。https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/BackgroundTransfer 上有一个完整的示例


查看完整回答
反对 回复 2021-11-21
?
守着星空守着你

TA贡献1799条经验 获得超8个赞

所以我决定在这里写下我自己的答案,因为我不确定其他人是否会解决这个问题。我怀疑的一件事是我最近将 C# 语言更新到了 v7.3,因为 VS 2017 在编写一些代码时是这样说的。也许问题与此有关,但到目前为止我的解决方案在最小化状态下工作。


我还想在此声明,我BackgroundTask首先实施以ApplicationTrigger在需要时触发该过程来克服这个问题,但老实说这是一种黑客攻击。看一下代码:


public static async Task<string> GetBackgroundTaskReturnValue(string apiRequestUrl)

{

        StaticItemsHelper.IsBackgroundPlaylistTaskRunning = true;

        if (StaticItemsHelper.IsBackgroundPlaylistTaskRunning)

        {

            for (int seconds = 0; seconds < 20;)

            {

                if (!StaticItemsHelper.IsBackgroundPlaylistTaskRunning)

                {

                    break;

                }

                else

                {

                    Task.Delay(1000).Wait();

                }

            }

        }

        var request = BackgroundTaskHelper.BackgroundPlaylistTrigger.RequestAsync().GetResults();

        if (request == Windows.ApplicationModel.Background.ApplicationTriggerResult.Allowed)

        {

            SettingsHelper.localSettings.Values[SettingsHelper.BackgroundPlaylistPlaybackURLKey] = apiRequestUrl;

            SettingsHelper.localSettings.Values[SettingsHelper.BackgroundPlaylistPlaybackTokenKey] = StaticItemsHelper.CurrentUserAccessToken;

            if (SettingsHelper.tempFolder.TryGetItemAsync(SettingsHelper.BackgroundPlaylistPlaybackReturnKey).GetResults() is StorageFile file)

            {

                await file.DeleteAsync();

            }

            for (int seconds = 0; seconds < 30;)

            {

                if (SettingsHelper.tempFolder.TryGetItemAsync(SettingsHelper.BackgroundPlaylistPlaybackReturnKey).GetResults() is StorageFile _rfile)

                {

                    var _returnVal = FileIO.ReadTextAsync(_rfile).GetResults();

                    if (!string.IsNullOrEmpty(_returnVal.ToString()))

                    {

                        await _rfile.DeleteAsync();

                        SettingsHelper.localSettings.Values.Remove(SettingsHelper.BackgroundPlaylistPlaybackTokenKey);

                        SettingsHelper.localSettings.Values.Remove(SettingsHelper.BackgroundPlaylistPlaybackURLKey);

                        StaticItemsHelper.IsBackgroundPlaylistTaskRunning = false;

                        return _returnVal;

                    }

                }

                Task.Delay(2000).Wait();

                seconds += 2;

            }

        }

        else if (request == Windows.ApplicationModel.Background.ApplicationTriggerResult.CurrentlyRunning)

        {

            for (int seconds = 0; seconds < 30;)

            {

                Task.Delay(2000).Wait();

                seconds += 2;

                request = BackgroundTaskHelper.BackgroundPlaylistTrigger.RequestAsync().GetResults();

                if (request == Windows.ApplicationModel.Background.ApplicationTriggerResult.Allowed)

                {

                    return GetBackgroundTaskReturnValue(apiRequestUrl).Result;

                }

            }

        }

        if (SettingsHelper.tempFolder.TryGetItemAsync(SettingsHelper.BackgroundPlaylistPlaybackReturnKey).GetResults() is StorageFile _file)

        {

            await _file.DeleteAsync();

        }

        SettingsHelper.localSettings.Values.Remove(SettingsHelper.BackgroundPlaylistPlaybackTokenKey);

        SettingsHelper.localSettings.Values.Remove(SettingsHelper.BackgroundPlaylistPlaybackURLKey);

        StaticItemsHelper.IsBackgroundPlaylistTaskRunning = false;

        return "{ \"error\": {\"code\": \"NetworkError\", \"message\": \"Server returned nothing.\"} }";

}

实际解决方案: 但是它也没有按我预期的那样工作,所以我决定放弃它并使用以下代码代替。(将此与问题进行比较)


public static async Task<string> GetResponseDataFromAPI(string apiRequestUrl, CancellationTokenSource cts = default)

{

        cts = cts ?? new CancellationTokenSource(TimeSpan.FromSeconds(20));

        try

        {

            if (StaticItemsHelper.IsAppInBackground)

            {

                //return await ViewHelper.GetBackgroundTaskReturnValue(apiRequestUrl);

                var responseData = AuthRequestHelper.globalHttpClient.GetAsync(apiRequestUrl, cts.Token).Result;

                var result = responseData.Content.ReadAsStringAsync().Result;

                return result;

            }

            else

            {

                var responseData = await AuthRequestHelper.globalHttpClient.GetAsync(apiRequestUrl, cts.Token);

                var result = await responseData.Content.ReadAsStringAsync();

                return result;

            }

        }

        catch (Exception ex)

        {

            INotifyHelper.iNotifyObject.IsDataLoading = false;

            // show error

            return "{ \"error\": {\"code\": " + $"\"{ex.HResult}\", \"message\": \"{ex.Message}\"" + "} }";

        }

}

希望这对其他人有所帮助。


查看完整回答
反对 回复 2021-11-21
  • 2 回答
  • 0 关注
  • 217 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信