I'm sure there's some other threads about this, but i think i need a threading for dummies or something.
My problem: I want to fetch a value by a WebRequest and display it. My code looks something like this:
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
This is a little bit simplified, but it's the same error as well. At the line with the comment "Here it crashes....." i get an exception with "The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))" I can how ever see that my result is fetched when i explore the Foo.
So, how is the right way to do this?
(And yes; if I enter a bad URL or something so that "WasError" is true, of course i get the same exception when i try to set my textblock to "ERROR")
EDIT: After some really strong words, blood sweat and tears, i came up with this change to the FetchValue(), and now it finally works....
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
I do how ever get a warning on the row in else that says "Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the Await operator to the result of the call."
Any ideas for how to make this warning go away?
It's far, far easier to do this with HttpClient
and Async
/Await
.
My VB is rusty, but here goes:
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
Usage:
Foo = New Fetcher()
Try
Dim data As String = Await Foo.Result
MyTextBlock.Text = data
Catch(Exception Ex)
MyTextBlock.Text = "ERROR"
End Try
Note that the Task<T>
type handles return values, error conditions, and completion notification. So all the posted code in your Fetcher
class is pretty much unnecessary if you use HttpClient
with Task<T>
. If your Fetcher
class doesn't do anything else, then you should probably just remove it entirely:
Dim client As HttpClient = New HttpClient()
Try
MyTextBlock.Text = Await client.GetStringAsync("theurl")
Catch(Exception Ex)
MyTextBlock.Text = "ERROR"
End Try
User contributions licensed under CC BY-SA 3.0