我试图让我的代码在单独的线程中工作,但无法使其工作。
我尝试使用委托(delegate)从互联网上跟踪几个不同的多线程示例,但没有解决我的问题。
我需要通过 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
关键字,这使此类事情变得更加容易。但是,您只能在 Await
对象上使用 Task
关键字。遗憾的是,由于 XDocument
没有提供方便的 LoadAsync
方法来返回 Task
对象,因此将它与基于任务的异步模式 (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
但是,通过在
Start
对象上调用 Task
方法,就像这样,它可能会启动一个新线程来完成工作。如果您担心解析 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,然后,一旦我们得到它,只需使用 XDocument
对象重新解析 XML 字符串调用线程。据推测,微软将在 future 版本的框架中向
LoadAsync
类添加一个 XDocument
方法,但在那之前你必须自己制作 Async
函数,就像我在上面的例子中所做的那样。如果您无法使用 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
关于xml - 使用 XDocument.Load 进行多线程,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28854961/