2014-01-07 23 views
1

我正在使用基于事件的第三方库。我真的只对调用库方法感兴趣,并知道库何时完成。几乎像这样:Convert Event based pattern to async CTP pattern使用后台文件传输Task.Wait()

事情是,图书馆似乎使用Windows Phone的Background File Transfer来完成它的工作。

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

我试图搜索有关在ThreadPool中运行后台文件传输的一些文档(因为我假设在我的异步代码中,这是库运行的地方),但无法真正找到任何信息。那么我的问题(该完成处理程序仅在超时后才被调用)是否后台文件传输代码不应该在ThreadPool中运行?

任何想法这种问题的好方法是什么?

+2

显然,你用'Task.Wait'阻止UI线程和消息泵,所以完成事件没有机会被正确触发。使用'await task'代替,并调用'async'的整个链。 – Noseratio

+0

也许我错过了一些东西,但我在这里遵循这个模式,它不使用async/await:http://stackoverflow.com/questions/12853445/convert-event-based-pattern-to-async-ctp-pattern/12853892#12853892 –

+0

您链接的模式是正确的。它不使用'async/await',但它不使用'Task.Wait()'。它返回一个Task对象,并且你希望这个任务异步地等待,而不是用'task.Wait()'来阻塞。随意发布更多相关的代码,我们可能会帮助解决它。要更好地理解这个问题,请阅读以下内容:http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html – Noseratio

回答

1

您链接的模式是正确的。它不使用async/await,但它也不使用Task.Wait()。它将返回一个Task对象,并且您预计将在该任务上异步执行await。也就是说,当任务达到完成(故障,取消)状态时,任务计划程序将异步调用await task之后的代码。

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

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

要更正您的代码,您必须完成调用async的整个链,直到根用户界面应用程序通常为事件处理程序。例如:

// 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上也有广泛的讨论)。

+0

感谢分享!这确实是我的问题。 –