我对异步编程还很陌生,但仍在尝试学习。我有一个应用程序,该应用程序读取巨大的XML文件(大约2GB),然后将其解析为表格。由于XMLreader需要大量时间,因此我需要异步方法。我创建了一个按钮(OnClick事件)异步并使用了任务/等待,但它给我一个错误(也许我没有正确使用它)。然后,在在线阅读后,我编写了以下代码(使用线程)。
Private Sub Parse_Btn_2G_Click(sender As Object, e As RoutedEventArgs) Handles Parse_Btn_2G.Click
Dim count As ArrayList
Dim action As Action
Dim Thread As Thread = New Thread(Sub()
count = CountXML()
action = Sub()
Status_Txtbox.Text = count(0).ToString() + " Managed Objects in XML"
End Sub
Me.Dispatcher.Invoke(action)
End Sub)
Thread.Start()
Status_Txtbox.Text = "Processing File. Please Wait...."
End Sub
CountXML是读取XML文件并计算属性的方法。这是用于计数属性的代码。
Private Function CountXML() As ArrayList
Dim settings As New XmlReaderSettings
settings.DtdProcessing = DtdProcessing.Ignore
settings.Async = True
Dim MONumbers As ArrayList = New ArrayList
Dim ADCEcount As Integer = 0
Dim BSCCount As Integer = 0
Dim BCFCount As Integer = 0
Dim TRXCount As Integer = 0
Dim desiredvalue As Boolean = True
Dim xReader As XmlReader = XmlReader.Create(xml_txtbox_2G.Text, settings)
Dim ns As XNamespace = XNamespace.Get("raml20.xsd")
While xReader.Read()
If xReader.Name <> "managedObject" Then
xReader.ReadToFollowing("managedObject")
End If
If Not xReader.EOF Then
Dim managedObject As XElement = XElement.ReadFrom(xReader)
If CType(managedObject.Attribute("class"), String) = "ADCE" Then
ADCEcount = ADCEcount + 1
End If
If CType(managedObject.Attribute("class"), String) = "BSC" Then
BSCCount = BSCCount + 1
End If
If CType(managedObject.Attribute("class"), String) = "BCF" Then
BCFCount = BCFCount + 1
End If
If CType(managedObject.Attribute("class"), String) = "TRX" Then
TRXCount = TRXCount + 1
End If
End If
End While
MONumbers.Add(ADCEcount)
MONumbers.Add(BSCCount)
MONumbers.Add(BCFCount)
MONumbers.Add(TRXCount)
Return MONumbers
End Function
当我不使用线程或等待/任务代码时,函数CountXML()可以很好地工作,但是一旦使用线程,我就会收到一条错误消息
System.InvalidOperationException:'调用线程无法访问 该对象,因为其他线程拥有它。'
我认为这是因为xml_txtbox_2G.Text是UI线程已使用的文本框控件(具有xml文件路径)。有人可以指导如何释放它,或者在读取xml文件时使用异步方法。谢谢
答案 0 :(得分:0)
我认为您可以通过较小的修改将问题投放到Async / Await
中。我尚未测试以下代码,但它与我编写的有效材料相似。
Private Async Sub Parse_Btn_2G_Click(sender As Object, e As RoutedEventArgs) Handles Parse_Btn_2G.Click
Status_Txtbox.Text = "Processing File. Please Wait...."
Dim count = Await CountXML
Status_Txtbox.Text = count(0).ToString() + " Managed Objects in XML"
End Sub
Private Async Function CountXML() As Task(Of ArrayList)
Dim asTask = Task.Run(Function() CountXMLImpl)
Return Await asTask
End Function
Private Function CountXMLImpl() As ArrayList
'Current contents of CountXML. You might name this and the async version differently if desired.
End Function
如果您想取消进行中的工作,则可以向Task.Run
提供取消令牌。以我的经验,这似乎只对排队等待线程的任务有影响,但没有积极处理。我没有研究强制执行中止和取消操作可能需要做的事情;也许正确的做法是将取消令牌作为基础例程的参数,并定期检查令牌是否已请求取消。
Private Async Function CountXML(ByVal cancellationSource as System.Threading.CancellationTokenSource)
Dim asTask = Task.Run(Function() CountXMLImpl, cancellationSource.Token)
Return Await asTask
End Function