【问题标题】:WebClient.DownloadFile in BackgroundWorker performance unacceptableBackgroundWorker 中的 WebClient.DownloadFile 性能无法接受
【发布时间】:2011-05-30 18:05:21
【问题描述】:

我有一个 WinForms 应用程序,每天需要下载许多(数万个)相当大(多 MB)的文件。我使用以下代码编写了一个简单的测试:

using (var wc = new System.Net.WebClient())
{
    foreach (string url in UrlsToDownload())
    {
        string targetPath = SafeFilePathOf(url);
        wc.DownloadFile(url, targetPath);
    }
}

目标机器的连接速度为 1 Gb/s,但测试显示持续下载速度约为 1MB/s。这比我预期的要少,但是源服务器的连接速度可能较慢。一整天的下载将需要几个小时的连接,这是可以接受的。网络利用率相当稳定,约为 1%:

但是,我需要在后台线程中执行下载并支持取消和下载进度。 .Net System.ComponentModel.BackgroundWorker 似乎是为此而设计的,所以我将完全相同的代码放在 BackgroundWorker 实例中并调用 RunWorkerAsync

下载性能下降到大约 0.05 MB/s。一天的工作大约需要一周的时间才能完成;这不会飞。

为什么BackgroundWorker 的性能这么差? CPU 和网络都没有过载。应用程序没有被阻止,我只是将下载代码从 UI 线程移到了BackgroundWorker。调用backgroundWorker.Priority = ThreadPriority.AboveNormal 无效。

【问题讨论】:

  • 在任何线程上的网络性能都没有区别,我认为它的其他报告性能等代码可能会减慢线程。你能发布你的 BG 线程的完整来源吗?
  • CPU 负载从 1% 飙升至 9%。先解决这个问题。
  • 我建议你使用异步版本 - DownloadFileAsync 无论如何。

标签: .net webclient backgroundworker


【解决方案1】:

增加 WebClient 的连接限制:

internal class CustomWebClient : WebClient
{
    public CustomWebClient()
    {
    }

    protected override WebRequest GetWebRequest(Uri uri)
    {
        HttpWebRequest w = (HttpWebRequest)base.GetWebRequest(uri);

        w.ServicePoint.ConnectionLimit = 100;
        return w;
    }
}

【讨论】:

    【解决方案2】:

    无论是后台线程还是 UI 线程,网络活动都执行相同的操作。问题可能是报告进度或记录活动等的任何其他代码。这可能会阻塞线程。

    【讨论】:

    • 你和汉斯的想法都是对的;它不是 BackgroundWorker,而是我的记录器。 UI 线程测试有一个空的日志文件,BackgroundWorker 线程试图在每次下载后解析一个多 MB 的日志文件。啊!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-10
    • 2016-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多