VB.Net多线程文件下载

时间:2013-04-10 17:48:49

标签: vb.net multithreading httpwebrequest

我有一个用VB.Net编写的winform应用程序,需要下载包含PubMed(医学期刊)文章数据的XML文件。我一次请求500篇文章的数据,因为我需要流式传输,我想避免加载一个超出可用内存的文件。在返回的文件中,每篇文章的数据都包含在<PubmedArticle>元素中:

<PubmedArticleSet>
    <PubmedArticle>
    ... (Article Data) ...
    </PubmedArticle>
    <PubmedArticle>
    ... (Article Data) ...
    </PubmedArticle>
</PubmedArticleSet>

我的代码看起来像这样(实际代码在每次迭代500个Pubmed ID的循环中执行下面的代码):

Dim pubmedIDs As String() = {"20816578", "20815951"}
Dim xmlUrl As String = String.Format("{0}{1}{2}", "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&id=", String.Join(",", pubmedIDs), "&retmode=xml&rettype=abstract")
Dim request as HttpWebRequest = DirectCast(WebRequest.Create(xmlUrl), HttpWebRequest)
Try
    Using response As WebResponse = request.GetResponse()
        Using responseStream As Stream = response.GetResponseStream()
            Dim xDoc As XDocument = XDocument.Load(responseStream)
            'Break up the requested file into one file per article and save them to a cache directory
            'Update a progress bar as files are cached
        End Using
    End Using
Catch ex As WebException
    'Handle HTTP errors by capturing Pubmed IDs of failed request to allow user to retry later
    'Update progress bar despite failed request to let user know when the process is finished
End Try

这一切都运行正常,但在典型的运行中,我需要收集20K +文件的文章数据,大约需要10分钟。有人可以就如何多线程处理请求给我建议吗?

1 个答案:

答案 0 :(得分:0)

一种可能是多线程解决方案的想法是将“网络读取”与“磁盘写入”分开。多线程磁盘写入可能不会导致性能优势(可能是高速网络存储的例外),但网络请求可能受益。因此,不是多线程整个块,而是这样:

  • 为传入的Queue个对象
  • 创建XmlDocument
  • 运行一个(或多个)线程来处理服务请求,并在响应到达时将对象推送到Queue
  • 运行一个单独的线程来监控Queue并将每个项目写入磁盘

这样,无论哪一方是瓶颈,整个过程都会接近最佳速度。然后,您可以在Queue的一侧或两侧试验多个线程,以查看并行请求/并行磁盘IO是否有用。

值得记住,您必须确保对Queue的线程安全访问,但这很容易解决(.NET中最简单的方法是使用Queue.Synchronized方法获取线程安全访问权限到现有的Queue)。