异步下载未通过IProgress.Report报告

编程入门 行业动态 更新时间:2024-10-15 22:31:40
本文介绍了异步下载未通过IProgress.Report报告的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我面临一个奇怪的问题,我必须承认-不明白.我有一个任务,正在异步从Web下载文件:

I'm facing a strange problem, which I must admit - do not understand. I've a Task, which is downloading a file from Web asynchronously:

public async Task DownloadFile(Uri requestUri, string fileName, IProgress<int> progress) { HttpWebRequest request = HttpWebRequest.CreateHttp(requestUri); request.Method = "GET"; request.AllowReadStreamBuffering = false; using (WebResponse response = await request.GetResponseAsync()) using (Stream mystr = response.GetResponseStream()) { StorageFolder local = ApplicationData.Current.LocalFolder; StorageFile file = await local.CreateFileAsync(fileName); using (Stream fileStream = await file.OpenStreamForWriteAsync()) { const int BUFFER_SIZE = 100 * 1024; byte[] buf = new byte[BUFFER_SIZE]; int bytesread = 0; // the problem is here below while ((bytesread = await mystr.ReadAsync(buf, 0, BUFFER_SIZE)) > 0) { await fileStream.WriteAsync(buf, 0, bytesread); progress.Report(bytesread); } } } }

该任务正在运行,但是如您所见,它应该报告其进度.

The Task is working, but as you can see it should Report its progress.

事实证明,问题出在程序到达行bytesread = await mystr.ReadAsync(buf, 0, BUFFER_SIZE)时-在下载完整个文件(不仅是BUFFER_SIZE)之前,该线程不会对该线程执行任何其他操作.完全下载后,while循环会被触发很多次,并从内存中复制流-速度非常快.

It turns out that the problem is when the program hits the line bytesread = await mystr.ReadAsync(buf, 0, BUFFER_SIZE) - it doesn't perform any other action on that thread until the whole file has been downloaded (not only BUFFER_SIZE). After the complete download the while loop is fired that many times it is needed and copies stream from memory - which goes quite fast.

奇怪的是,同一代码在WP8.0上正常工作,现在,我尝试在WP8.1上运行它,而我正面临着这个问题.有人知道我在做什么错吗?

The strange thing is that the same code was working without issue on WP8.0, now I try to run it on WP8.1 and I'm facing this problem. Does anybody has an idea what I'm doing wrong?

推荐答案

要记住的一件事是IProgress<T>.Report本身是异步的".从某种意义上说,不是返回Task,而是从进度报告实现到Report返回时可能还没有完成其实际进度报告.特别是,Progress<T>.Report将在调用其委托或事件处理程序之前将进度报告封送给捕获的SynchronizationContext.

One thing to keep in mind is that IProgress<T>.Report is itself "asynchronous". Not in the sense that it returns a Task, but in the sense that the progress reporting implementation may not have done its actual progress reporting by the time Report returns. In particular, Progress<T>.Report will marshal a progress report to a captured SynchronizationContext before invoking its delegate or event handler.

通常,这正是您想要的:如果在UI线程上创建Progress<T>,则其委托/事件处理程序将在UI线程上执行,您不必担心跨线程封送处理使用进度报告更新用户界面时.

Normally, this is exactly what you want: if you create a Progress<T> on the UI thread, then its delegate/event handler is executed on the UI thread, and you don't have to worry about cross-thread marshaling when updating your UI with the progress report.

在这种情况下,我相信您看到的是WP8.1进行了一些积极的缓存.微软确实一直在推动WP的缓存.如果我的猜测是正确的,那么您看到的行为是由于ReadAsync同步完成(响应已在HTTP缓存中)以及WriteAsync同步完成(缓冲的文件写入)引起的.在这种情况下,await都不会实际产生,因此IProgress<T>.Report调用只是堆积起来,等待它们有机会在UI线程上运行.

In this case, I believe what you're seeing is some aggressive caching by WP8.1. Microsoft has really been pushing the caching on WP. If my guess is correct, then the behavior you're seeing is due to ReadAsync completing synchronously (response is already in HTTP cache) as well as WriteAsync completing synchronously (buffered file writes). In this case, none of the awaits will ever actually yield, so the IProgress<T>.Report calls just stack up waiting for their chance to run on the UI thread.

在开发过程中,缓存通常只是一个问题".如果您确实希望最终用户遇到这种情况,则可以在while循环中添加await Task.Yield();.

Caching is usually just a "problem" during development. If you do expect your end users to encounter this situation, you can add an await Task.Yield(); into your while loop.

更多推荐

异步下载未通过IProgress.Report报告

本文发布于:2023-11-08 10:35:59,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1569150.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:报告   IProgress   Report

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!