c# - 在 C# 中从 Internet 下载文件并即时写入的正确方法是什么?

标签 c# .net multithreading compact-framework download

编辑:这是在 Compact Framework 中完成的,我无权访问 WebClient,因此必须使用 HttpWebRequests 完成。

我正在创建一个下载管理器应用程序,它将能够进行并发下载(一次下载多个)并能够报告已完成的百分比并恢复下载。

这意味着我正在将一些字节下载到缓冲区中,然后将缓冲区写入磁盘。我只是想检查为此推荐的算法/过程是什么。

这是我到目前为止的主要下载方法:

    private void StartDownload()
    {
        HttpWebRequest webReq = null;
        HttpWebResponse webRes = null;
        Stream fileBytes = null;
        FileStream saveStream = null;

        try
        {
            webReq = (HttpWebRequest)HttpWebRequest.Create(_url);
            webReq.Headers.Add(HttpRequestHeader.Cookie, "somedata");
            webRes = (HttpWebResponse)webReq.GetResponse();

            byte[] buffer = new byte[4096];
            long bytesRead = 0;
            long contentLength = webRes.ContentLength;

            if (File.Exists(_filePath))
            {
                bytesRead = new FileInfo(_filePath).Length;
            }

            fileBytes = webRes.GetResponseStream();
            fileBytes.Seek(bytesRead, SeekOrigin.Begin);

            saveStream = new FileStream(_filePath, FileMode.Append, FileAccess.Write);

            while (bytesRead < contentLength)
            {
                int read = fileBytes.Read(buffer, 0, 4096);
                saveStream.Write(buffer, 0, read);
                bytesRead += read;
            }
            //set download status to complete
            //_parent
        }
        catch
        {
            if (Thread.CurrentThread.ThreadState != ThreadState.AbortRequested)
            {
               //Set status to error.
            }
        }
        finally
        {
            saveStream.Close();
            fileBytes.Close();
            webRes.Close();
            saveStream.Dispose();
            fileBytes.Dispose();
            saveStream = null;
            fileBytes = null;
            webRes = null;
            webReq = null;
        }
    }

我应该下载更大的缓冲区吗?我是否应该如此频繁地将缓冲区写入文件(每 4KB 一次?)是否应该有一些线程在其中休眠以确保不会使用所有 CPU?我认为每 4KB 报告进度变化是愚蠢的,所以我计划每下载 64KB 就报告一次。

目前正在寻找一些通用提示或我的代码存在的任何错误。

最佳答案

首先,我会去掉 finally 子句并更改代码以使用“USING”子句。

任何实现 IDisposable 的东西都应该以这种方式编程,以确保垃圾收集正确发生并且在它应该发生的时候发生。

例如:

using (HttpWebRequest webReq = (HttpWebRequest)HttpWebRequest.Create(_url)) {
    /* more code here... */
}

其次,我不会在头部用空值实例化我的变量(ala Pascal 风格)。见上例。

第三,下载应该在它自己的线程中进行,该线程与主线程中的回调函数同步以报告状态。将同步调用放在 while 循环的中间。

关于c# - 在 C# 中从 Internet 下载文件并即时写入的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2028886/

相关文章:

c++ - 从另一个任务创建任务 - 用线程池库替换 std::async 时出现死锁

Java 网络 - 在同一线程中的不同端口上并行启动多个服务器套接字

c# - 如何检查程序集是否已更改

c# - 无法启动 xxx.exe。先前对应用程序进行概要分析的尝试未成功完成。请重新启动应用程序

c# - URL 重写以删除 www 并使用 web-config (c# .net) 重定向到 https

Python线程进程不阻止 'Not responding'

c# - GridView RowUpdating 没有获取新数据

c# - Aluminium Lua - 寄存器函数

c# - 为什么 SortedList<TKey, TValue> 不对值使用指针?

c# - Moq 4.13.1 与 Task.Extensions 不兼容