我试图让我的代码在一个单独的线程中工作,但不能使它工作.
我曾尝试使用代理从互联网上关注几个不同的多线程示例,但没有解决我的问题.
我曾尝试使用代理从互联网上关注几个不同的多线程示例,但没有解决我的问题.
我需要通过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