【问题标题】:Windows background task API async functions issueWindows 后台任务 API 异步函数问题
【发布时间】:2014-05-07 02:58:43
【问题描述】:

我在 windows phone 8.1 中使用定时器触发后台任务 API。

我只是想了解此 API 的基础知识。

我有一个注册定时器触发后台任务的应用程序。每 15 分钟触发一次事件。我知道应用程序的入口点有这个叫做 RUN 的函数。

我正在尝试使用后台传输服务 API 上传一张简单的图片。由于这个 API 是异步的,我使用 BackgroundTaskDeferral 来确保后台任务 API 遵循异步操作。

这是我注意到的,当您将上传作为单独的函数并在 RUN 方法中调用它时,它会在大约 10 秒内关闭。但是如果你在 RUN 函数本身中有完整的代码,它会持续大约 10 分钟。

有没有办法可以覆盖这个功能?或者知道为什么会这样?

public async void Run(IBackgroundTaskInstance taskInstance)
{

    BackgroundTaskDeferral _deferral = taskInstance.GetDeferral();

    //accessMediaUpload();

    StorageFolder picfolder = KnownFolders.CameraRoll;
    var x = await picfolder.GetFilesAsync();
    var enumerator = x.GetEnumerator();

    Debug.WriteLine("Number of files are: " + x.Count);

    while (enumerator.MoveNext())
    {
         var file = enumerator.Current;

         BackgroundUploader uploader = new BackgroundUploader();
         uploader.SetRequestHeader("Filename", file.Name);

         UploadOperation upload = uploader.CreateUpload(uri, file);
         await upload.StartAsync();

         // Get the HTTP response to see the upload result
         ResponseInformation response = upload.GetResponseInformation();
         if (response.StatusCode == 200)
         {
             Debug.WriteLine(file.Name + " Uplaoded");
         }      
     }
     _deferral.Complete();
}

如上所示的代码是 RUN 方法,它是后台任务的入口点。这里我有一个名为 accessMediaUpload() 的注释函数。该函数只包含如上所示的将文件上传到服务器的代码。

如果去掉内联上传代码并取消注释 accessMediaUpload(),后台任务将只运行几秒钟。但上面的代码运行良好。

【问题讨论】:

  • 我怀疑你读过remarks here at MSDN。你能分享一个工作示例或代码吗?
  • @Romasz 我已经添加了我现在正在处理的示例代码!
  • 这段代码会保持工作 10 分钟或 10 秒?
  • 此代码运行 10 分钟。如果我从这里取出上传代码并取消对 accessMediaUpload() 函数的注释,它只会运行 10 秒。

标签: windows-phone-8 windows-phone windows-8.1 windows-phone-8.1


【解决方案1】:

我没有尝试过代码,因为我现在没有工作示例。但据我了解from MSDN,你应该在计划运行异步任务时获得Defferal,并在完成后调用Complete()

BackgroundTaskDeferral _deferral;

public async void Run(IBackgroundTaskInstance taskInstance)
{
    _deferral = taskInstance.GetDeferral();
    accessMediaUpload();
}

private async Task accessMediaUpload()
{
    StorageFolder picfolder = KnownFolders.CameraRoll;
    var x = await picfolder.GetFilesAsync();
    var enumerator = x.GetEnumerator();

    Debug.WriteLine("Number of files are: " + x.Count);

    while (enumerator.MoveNext())
    {
         var file = enumerator.Current;

         BackgroundUploader uploader = new BackgroundUploader();
         uploader.SetRequestHeader("Filename", file.Name);

         UploadOperation upload = uploader.CreateUpload(uri, file);
         await upload.StartAsync();

         // Get the HTTP response to see the upload result
         ResponseInformation response = upload.GetResponseInformation();
         if (response.StatusCode == 200)
         {
             Debug.WriteLine(file.Name + " Uplaoded");
         }      
     }
     _deferral.Complete();
}

几点说明:

  • 请注意,IMO 您应该将 _deferral.Complete(); 放入 try-catch-finallyfinally 块中 - 只是为了确保即使出现异常也能调用它。正如 MSDN 所说的

    始终小心完成所有获得的后台任务延迟。系统不会挂起或终止后台主机进程,直到其所有挂起的后台任务延迟完成。让后台任务延迟未完成会干扰系统管理进程生命周期的能力,并会导致资源泄漏。

  • 上面的方法可能会有所改进,因为您可以分别为每个任务获取延迟(如果您有多个任务)并在其结束时调用 Complete。这应该允许您运行多个任务并在所有异步任务完成后完成整个BackgroundTask(称为Complete()

【讨论】:

  • @golldy 然后再给我一点时间 - 我会在答案中添加一些评论。
  • @Romasz :你能用一个例子解释你的最后一点吗?就像如何为每个任务获得多个延期一样。您不会只使用从 taskInstance 创建的相同延迟吗?
  • @AbsoluteSith 请阅读remarks section from documentation
猜你喜欢
  • 2022-09-25
  • 1970-01-01
  • 2021-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多