我确定还有一些关于此问题的其他线索,但我认为我需要对傻瓜或其他东西进行线程处理。
我的问题:我想通过WebRequest获取值并显示它。我的代码看起来像这样:
Foo = New Fetcher()
AddHandler Foo.HasResult, AddressOf Me.FetchValue
Private Sub FetchValue()
If Foo.HasErrors Then
MyTextBlock.Text = "ERROR"
Exit Sub
End IF
MyTextBlock.Text = Foo.Value 'Here it crashes.....
End sub
Public Class Fetcher
Public Event HasResult(ByVal F As Fetcher)
Public WasError As Boolean = True
Public Value As String = ""
Public Sub New()
Dim request As WebRequest = WebRequest.Create("theurl")
request.BeginGetResponse(New AsyncCallback(AddressOf Me.GetValueAnswer), request)
End Sub
Private Sub GetValueAnswer(asynchronousResult As IAsyncResult)
Dim request As HttpWebRequest = asynchronousResult.AsyncState
If Not request Is Nothing Then
Try
Dim response As WebResponse = request.EndGetResponse(asynchronousResult)
Using stream As Stream = response.GetResponseStream()
Using reader As New StreamReader(stream, System.Text.Encoding.UTF8)
Dim responseString = reader.ReadToEnd()
Me.Value = ResponseString
Me.WasError = False
End Using
End Using
Catch(Exception Ex)
Me.WasError = True 'Not needed in this example, i know...
End Try
End If
RaiseEvent HasResult(Me)
End Sub
End Class
这有点简化,但也是同样的错误。 在注释“Here it crashes .....”的行中,我得到一个例外,“应用程序调用了一个为不同线程编组的接口。(HRESULT异常:0x8001010E(RPC_E_WRONG_THREAD))” 当我探索Foo时,我怎么能看到我的结果被取出。
那么,正确的方法是怎样的呢?
(是的;如果我输入一个错误的URL或某些东西,以便“WasError”为真,当我尝试将我的文本块设置为“ERROR”时,我会得到相同的异常)
编辑:在一些非常强烈的话语,血汗和泪水之后,我想出了对FetchValue()的这种改变,现在它终于有效了....If Me.MyTextBlock.Dispatcher.HasThreadAccess Then
If Foo.HasErrors Then
MyTextBlock.Text = "ERROR"
Exit Sub
End IF
MyTextBlock.Text = Foo.Value
Else
Me.MyTestBlock.Dispatcher.RunAsync(Core.CoreDispatcherPriority.Normal, _
AddressOf Me.FetchValue)
End If
我确实在其他地方的行中收到警告“因为没有等待此调用,当前方法的执行在调用完成之前继续。考虑将Await运算符应用于调用的结果。”
关于如何发出此警告的任何想法都会消失?
答案 0 :(得分:1)
使用HttpClient
和Async
/ Await
执行此操作要容易得多。
我的VB生锈了,但这里有:
Public Class Fetcher
Public Result As Task(of String)
Public Sub New()
Dim client As HttpClient = New HttpClient()
Result = client.GetStringAsync("theurl")
End Sub
End Class
用法:
Foo = New Fetcher()
Try
Dim data As String = Await Foo.Result
MyTextBlock.Text = data
Catch(Exception Ex)
MyTextBlock.Text = "ERROR"
End Try
请注意,Task<T>
类型处理返回值,错误条件和完成通知。因此,如果您将Fetcher
与HttpClient
一起使用,则Task<T>
课程中的所有已发布代码都是非常不必要的。如果您的Fetcher
课程没有做任何其他事情,那么您应该完全删除它:
Dim client As HttpClient = New HttpClient()
Try
MyTextBlock.Text = Await client.GetStringAsync("theurl")
Catch(Exception Ex)
MyTextBlock.Text = "ERROR"
End Try