【问题标题】:Working with Background File Transfer with Task.Wait()使用 Task.Wait() 处理后台文件传输
【发布时间】:2014-01-08 11:08:59
【问题描述】:

我正在使用基于事件的第 3 方库。我真的只对调用库方法和知道库何时完成感兴趣。很像这里:Convert Event based pattern to async CTP pattern

问题是该库似乎使用 Windows Phone 的Background File Transfer 来完成它的工作。

我的症状是库的完成处理程序仅在我的Task.Wait(TimeSpan.FromSeconds(5)) 超时后才被调用。

我试图搜索一些关于在 ThreadPool 中运行后台文件传输的文档(正如我在我的异步代码中假设的那样,这就是库正在运行的地方),但实际上找不到任何信息。那么我的问题(仅在超时后才调用完成处理程序)可能是后台文件传输代码不应该在线程池中运行吗?

你知道解决这类问题的好方法是什么吗?

【问题讨论】:

  • 显然,您正在使用Task.Wait 阻塞 UI 线程及其消息泵,因此完成事件没有机会被正确触发。改用await task 并进行整个调用链async
  • 也许我遗漏了什么,但我在这里遵循这种模式,它不使用 async/await:stackoverflow.com/questions/12853445/…
  • 您链接的模式是正确的。它不使用async/await,但也不使用Task.Wait()。它返回一个Task 对象,并且您应该在该任务上异步await,而不是使用task.Wait() 阻塞。随意发布更多相关代码,我们可能会帮助修复它。为了更好地理解这个问题,请阅读:blog.stephencleary.com/2012/07/dont-block-on-async-code.html
  • 感谢您澄清和指出我的误解。我现在完全理解我的问题了。并随时发布您的评论作为答案,我会将其标记为对此问题的答案。
  • 没问题,我已经发布了包含一些附加信息的答案。

标签: c# .net windows-phone-8 backgroundworker async-await


【解决方案1】:

您链接的模式是正确的。它不使用async/await,但也不使用Task.Wait()。它返回一个Task 对象,您应该在该任务上异步await。这意味着,await task 之后的代码将在任务达到完成(故障、取消)状态时由任务调度程序异步调用。

否则,您将通过同步 Task.Wait() 调用阻塞 UI 线程及其消息泵,因此完成事件没有机会被正确触发。

为了更好地理解这个问题,这里有一个很好的阅读:Don't Block on Async

要更正您的代码,您必须进行整个调用链async,直到根,在 UI 应用程序中通常是一个事件处理程序。例如:

// note, "async void" is normally only good for async event handler
async void buttonTest_Click(object sender, EventArgs e)
{
    try
    {
        var task = DownloadStringAsync("http://example.com"); // for example 
        // Wrong: task.Wait();      
        await task;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

顺便说一句,现在您还有其他事情要担心。 UI 不再被阻塞,而异步操作仍在进行中。因此,您的用户可能会再次单击Test 按钮,并且您突然有两个待处理的异步操作。您应该考虑这种情况(在 SO 上也对此进行了广泛讨论)。

【讨论】:

  • 感谢分享!这确实是我的问题。
猜你喜欢
  • 2015-02-23
  • 1970-01-01
  • 1970-01-01
  • 2020-11-05
  • 2011-08-10
  • 1970-01-01
  • 1970-01-01
  • 2020-09-17
  • 1970-01-01
相关资源
最近更新 更多