【问题标题】:Problems with threading and WebRequests线程和 WebRequest 的问题
【发布时间】:2014-07-17 12:23:41
【问题描述】:

我确定还有其他一些关于此的线程,但我认为我需要一个用于假人或其他东西的线程。

我的问题:我想通过 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

这有点简化,但也是同样的错误。 在带有注释“这里它崩溃了.....”的行中,我得到一个异常“应用程序调用了一个为不同线程编组的接口。(来自 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

我怎么会在 else 的行上收到一条警告,上面写着“因为没有等待此调用,所以在调用完成之前继续执行当前方法。考虑将 Await 运算符应用于调用结果。”

关于如何消除此警告的任何想法?

【问题讨论】:

  • 您不能使用与 UI 线程不同的线程写入文本框。你必须使用 Invoke,看看这个stackoverflow.com/questions/16529092/…
  • 谢谢。我试图做与该线程中解释的类似的事情,但我不能在我的文本框中使用 .InvokeRequired 。它说它不是该类的成员,我无法在智能感知中得到任何关于调用的信息。
  • 你的文本框是 System.Windows.Forms.TextBox 吗?
  • 不,但它是一个 Windows.UI.Xaml.Controls.TextBox (实际上,它是一个 textBLOCK,类似于标签的东西......无论我使用什么控件都存在同样的问题)跨度>
  • 我不是很熟悉,但似乎您必须使用 .Dispatcher 属性。 stackoverflow.com/questions/710034/…

标签: vb.net multithreading winrt-xaml webrequest


【解决方案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> 类型处理返回值、错误条件和完成通知。因此,如果您将HttpClientTask<T> 一起使用,那么在您的Fetcher 类中发布的所有代码几乎都是不必要的。如果您的 Fetcher 类没有做任何其他事情,那么您可能应该完全删除它:

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

【讨论】:

  • 这看起来真不错!我从http得到的答案是json,所以我必须解析它和其他东西,所以我想我会把它放在一个类中——但这看起来确实更好。我会试试这个! :)
猜你喜欢
  • 2011-11-02
  • 2010-12-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-17
  • 2017-01-15
  • 2011-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多