2

重複の可能性:
クロススレッド例外の修正

非同期 HTTP リクエストを使用して Web リクエストを送信し、UI をブロックすることなくレスポンスを取得しています。これは、応答をフォームのラベルに配置しようとするまでは正常に機能し、その時点で「クロススレッド操作が無効です: 作成されたスレッド以外のスレッドからアクセスされたコントロール」が表示されます。さまざまなスレッドからコントロールにアクセスする際の問題と、それを回避するためのデリゲートの使用に関する問題を認識しています。

Web コールバック コードが別のスレッドで実行されているため、元のスレッドで作成されたコントロールにアクセスできないのではないかと思いますが、コールバックが追加のスレッドを使用する方法を完全には理解していないと思います。最初の場所。

私が欲しいのは、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

これは以前にも何度も答えられたと思います。UIスレッドで更新を実行するには、Control.Invoke関数を使用する必要があります。

于 2012-10-18T19:49:15.073 に答える
1

エラーの行を次のように置き換えます。

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