xml – 使用XDocument.Load进行多线程处理

我试图让我的代码一个单独的线程中工作,但不能使它工作.
我曾尝试使用代理从互联网上关注几个不同的多线程示例,但没有解决我的问题.

我需要通过URL从XML文件加载数据,然后在标签显示XML中的一些数据.加载XML有时需要很长时间,而且我的应用程序在加载过程中没有响应.我不知道还应该尝试什么.

这是一个可以在没有多线程的情况下加载XML的示例(使UI无响应):

Dim xmlRoot1 As XElement = XDocument.Load("http://example.com/api/books.xml").Root
Label1.Text = xmlRoot1.<bookstore>.<book>(0).<title>.Value
Label2.Text = xmlRoot1.<bookstore>.<book>(1).<title>.Value
' ...

这是我正在加载的XML的示例:

<xml>
<bookstore>
    <book>
        <title>Everyday Italian</title>
        <author>Giada De Laurentiis</author>
        <year>2005</year>
        <price>30.00</price>
    </book>
    <book>
        <title>Harry Potter</title>
        <author>J K. Rowling</author>
        <year>2005</year>
        <price>29.99</price>
    </book>
    <book>
        <title>XQuery Kick Start</title>
        <author>James McGovern</author>
        <year>2003</year>
        <price>49.99</price>
    </book>
    <book>
        <title>Learning XML</title>
        <author>Erik T. Ray</author>
        <year>2003</year>
        <price>39.95</price>
    </book>
    </bookstore>
</xml>

解决方法

如果您使用的是Visual Studio 2012和4.5或更高版本的框架,则可以访问Async和Await关键字,从而使这样的事情变得更加容易.但是,您只能在Task对象上使用Await关键字.由于XDocument遗憾地没有提供返回Task对象的方便的LoadAsync方法,因此使用基于任务的异步模式(TAP)更加困难.最简单的方法是创建一个这样的方法

Public Async Function LoadXDocumentAsync(uri As String) As Task(Of XDocument)
    Dim t As New Task(Of XDocument)(Function() XDocument.Load(uri))
    t.Start()
    Return Await t
End Function

然后你可以像这样调用它:

Dim doc As XDocument = Await LoadXDocumentAsync("http://example.com/api/books.xml")
Label1.Text = doc.Root.<bookstore>.<book>(0).<title>.Value
Label2.Text = doc.Root.<bookstore>.<book>(1).<title>.Value

但是,通过在Task对象上调用Start方法,它可能会启动一个新线程来完成工作.如果你担心解析XML会花费很长时间,那么这是最好的事情,但是如果你只关心下载时间,那么创建一个单独的线程只是让它坐在那里技术上是低效的从URI下载XML时空闲.所以,虽然它有点复杂,但如果你只关心异步执行的下载,那么在技术上做这样的事情效率更高:

Public Async Function LoadXDocumentAsync(uri As String) As Task(Of XDocument)
    Dim client As New WebClient()
    Return XDocument.Parse(Await client.DownloadStringTaskAsync(uri))
End Function

然后,您可以使用与第一个示例相同的方式调用它.第二个示例利用了WebClient类确实提供了我们可以使用的基于任务的Async方法这一事实.因此,即使XDocument没有提供基于任务的Async方法,我们仍然可以使用基于任务的WebClient方法至少下载XML,然后,一旦我们得到它,只需重新解析XML字符串和XDocument对象调用线程.

据推测,微软将在未来的某个版本的框架中向XDocument类添加一个LoadAsync方法,但在此之前你必须自己制作异步函数,就像我在上面的例子中所做的那样.

如果您无法使用TAP,我建议使用BackgroundWorker组件.例如:

Public Class Form1
    Private _doc As XDocument

    Private Sub Button1_Click(sender As Object,e As EventArgs) Handles Button1.Click
        BackgroundWorker1.RunWorkerAsync()
    End Sub

    Private Sub BackgroundWorker1_DoWork(sender As Object,e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        _doc = XDocument.Load("http://example.com/api/books.xml")
    End Sub

    Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object,e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        Label1.Text = _doc.Root.<bookstore>.<book>(0).<title>.Value
        Label2.Text = _doc.Root.<bookstore>.<book>(1).<title>.Value
    End Sub
End Class

相关文章

php输出xml格式字符串
J2ME Mobile 3D入门教程系列文章之一
XML轻松学习手册
XML入门的常见问题(一)
XML入门的常见问题(三)
XML轻松学习手册(2)XML概念