线程和WebRequests的问题

时间:2014-07-17 12:23:41

标签: vb.net multithreading winrt-xaml webrequest

我确定还有一些关于此问题的其他线索,但我认为我需要对傻瓜或其他东西进行线程处理。

我的问题:我想通过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运算符应用于调用的结果。”

关于如何发出此警告的任何想法都会消失?

1 个答案:

答案 0 :(得分:1)

使用HttpClientAsync / 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>类型处理返回值,错误条件和完成通知。因此,如果您将FetcherHttpClient一起使用,则Task<T>课程中的所有已发布代码都是非常不必要的。如果您的Fetcher课程没有做任何其他事情,那么您应该完全删除它:

Dim client As HttpClient = New HttpClient()
Try
    MyTextBlock.Text = Await client.GetStringAsync("theurl")
Catch(Exception Ex)
    MyTextBlock.Text = "ERROR"
End Try