2

可能重复:
修复跨线程异常

我正在使用异步 HTTP 请求来发送 Web 请求并在不阻塞 UI 的情况下获取响应。这工作正常,直到我尝试将响应放入表单上的标签中,此时我得到“跨线程操作无效:从创建它的线程以外的线程访问的控件”。我知道从不同线程访问控件的问题,以及使用委托来解决它的问题。

我怀疑正在发生的事情是 web 回调代码在不同的线程上执行,因此它无法访问在原始线程上创建的控件,但我想我不完全理解回调如何在第一名。

我想要的是能够发出网络请求,继续其他业务,然后在响应到达时获取响应,并能够将响应放置在控件上

Public Sub Test()
    SendAsynchRequest("http://google.com")
End Sub

Public Sub SendAsynchRequest(ByVal MyURL As String, Optional ByVal Timeout As Integer = 30)
    'send an asynch web request

    Dim request As HttpWebRequest
    Dim result As IAsyncResult
    Dim state As WebRequestState
    Dim reqtimeout As Integer

    Try
        request = CType(WebRequest.Create(MyURL), HttpWebRequest)   ' Create the request
        request.Proxy = Nothing

        state = New WebRequestState(request)        ' Create the state object used to access the web request
        result = request.BeginGetResponse(New AsyncCallback(AddressOf RequestComplete), state)
        reqtimeout = 1000 * Timeout
        ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, New WaitOrTimerCallback(AddressOf TimeoutCallback), state, reqtimeout, True)

    Catch ex As Exception
        log.Error("Error sending web request: " & ex.Message)

    End Try

End Sub

Private Sub TimeoutCallback(ByVal state As Object, ByVal timeOut As Boolean)
    'request times out    
    If (timeOut) Then
        ' Abort the request
        CType(state, WebRequestState).Request.Abort()
        Dim orig_url = CType(state, WebRequestState).Request
        log.Error("Web request to: " & orig_url.RequestUri.ToString & " timed out")
    End If
End Sub

Private Sub RequestComplete(ByVal result As IAsyncResult)
    'called when the request completes

    Dim request As WebRequest
    Dim response As System.IO.Stream
    Dim sr As StreamReader

    Try
        request = DirectCast(result.AsyncState, WebRequestState).Request
        response = request.EndGetResponse(result).GetResponseStream
        sr = New StreamReader(response)
        log.Info("Received Web response: " & sr.ReadToEnd)

        '*********************************************************
        ' THIS LINE CAUSES A CROSS-THREAD ERROR
        '*********************************************************
        TextBox1.Text = sr.ReadToEnd

    Catch ex As Exception
        log.Error("Received error code: " & ex.Message)

    End Try

End Sub

Private Class WebRequestState
    'Stores web request for access during async processing
    Public Request As WebRequest

    Public Sub New(ByVal newRequest As WebRequest)
        Request = newRequest
    End Sub
End Class
4

2 回答 2

1

在错误行中,替换为以下内容:

TextBox1.Invoke(Sub()
                   TextBox1.Text = sr.ReadToEnd
                End Sub)
于 2012-10-18T19:58:31.767 回答
1

我敢肯定,这个问题之前已经回答过很多次了。您需要使用 Control.Invoke 函数在 UI 线程上运行更新。

于 2012-10-18T19:49:15.073 回答