【问题标题】:Process download data asynchronous异步处理下载数据
【发布时间】:2015-02-02 11:48:05
【问题描述】:

是否有一种简单的方法可以在下载仍在运行时处理加载的数据? 我不想等待下载完成以在处理之前将整个数据保存在内存或磁盘上。我想这样做是因为我的数据是压缩的,我想解压缩字节运行中的数据包并将它们直接写入磁盘。这样我就不会使用超过一个下载包的内存。

我试图与 WebClient 类相处,但我没有找到如何在 DownloadProgressChanged 事件中访问最后加载的字节。

类似这样的:

WebClient wc = new WebClient();
Uri uri = new Uri(myURL);
wc.DownloadProgressChanged += wc_DownloadProgressChanged;
wc.DownloadDataAsync(uri);

...

void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    ProcessData(e.Bytes,e.BytesReceived); //e.Bytes should access the downloaded byte packet
    //but it doesn't exist
}

我已经使用 libcurl 解决了这个问题,但我想知道是否可以不使用外部库。

【问题讨论】:

  • 您可以随时使用 HTTP 请求甚至 TCP 连接来获得更好的控制,.NET 有两个选项的类。
  • 谢谢,我去看看。

标签: c# .net download webclient asynchronous


【解决方案1】:

没有机会对其进行测试,但它可以像这样工作:

    public void DownloadFileAsync()
    {
        WebClient wc = new WebClient();
        Uri uri = new Uri(myURL);
        //Open Stream from URI
        wc.OpenReadCompleted += new OpenReadCompletedEventHandler(OpenReadCallback);
        wc.OpenReadAsync(uri);
    }


    private static void OpenReadCallback(Object sender, OpenReadCompletedEventArgs e)
    {
        Stream resStream = null;

        try
        {
            resStream = (Stream)e.Result;
            //Your decompression stream Gzip for example
            using (GZipStream compressionStream = new GZipStream(resStream, CompressionMode.Decompress))
            {
                //write gzip stream to file
                using (
                    FileStream outFile = new FileStream(@"c:\mytarget.somefile", FileMode.Create, FileAccess.Write,
                        FileShare.None))
                      compressionStream.CopyTo(outFile);
            }
        }
        finally
        {
            if (resStream != null)
            {
                resStream.Close();
            }
        }
    }

【讨论】:

  • "await 运算符应用于异步方法中的任务,以暂停方法的执行,直到等待的任务完成。"我想通过“等待”我有关于记忆的完整数据,这是我一开始不想要的。还是我错了?
  • await 操作符只是等待异步任务完成。 await 之后的操作仍然异步执行,因此您不会将整个数据保存在内存中。异步等待只是管理整个调度的事情,你必须在使用线程时手动执行。
  • 好的,谢谢!那已经是东西了。但是当下载完成时,我不会将整个数据加载到我的流/内存中吗?还是每次解压+复制到磁盘后释放最后一个流数据?
  • 抱歉,代码不起作用,只是注意到 OpenReadAsync 不会返回 Task,因此您需要在 OpenReadCompleted 事件上注册。我会修复代码。对于您的最后一条评论,除非您读取以某些字节 [] 或类似操作结束的流,否则您不会将全部数据保存在内存中。
  • 我猜你必须将事件处理程序中的 CopyTo 推送到一个单独的线程中,形成 WebClient 的源我猜事件被调度回 ui 线程,所以 ui 线程或调用 OpenReadAsync 的线程,所以当您复制流时,此线程将被阻止
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-27
  • 1970-01-01
  • 2014-02-13
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
相关资源
最近更新 更多