使用Task.Wait()处理后台文件传输



我正在使用一个基于事件的第三方库。我真正感兴趣的只是调用库方法并知道库何时完成。很像这里:将基于事件的模式转换为异步CTP模式

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

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

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

有什么想法可以解决这类问题吗?

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

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

为了更好地理解这个问题,这里有一个非常好的阅读:不要在异步上阻塞。

要更正代码,您必须进行整个调用链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上也有广泛讨论)。

最新更新