问题
I am an absolute beginner on ASP.net (VB.) Please pardon me if the question is too obvious for the experienced members.
I tried to make a simple WebRequest in the async mode in case the target URL takes long to provide the data. In my code below, I just want to see if the callback block (RespCallback) is called correctly every time. If all goes well, lblResult should have the string '123' appended to it every time I click the button which calls the 'GetData' sub.
However, the lblResult only shows 123 after the first click. After the subsequent click, the lblResult only gets appended with '12', as if RespCallback is never called. When I tried to debug this in Visual Studio, the execution actually stepped right into the RespCallback part and the lblResult.Text watch actually shows '123123' but the resulting Web page always shows only '12312'
I am sure I am missing something basic here, but I just don't know what. I was even guessing that it has to do with browser cache (hence the result changes for the second time) but I don't know how to fix that either.
Can someone please help? Thanks in advance.
Jim
Dim myWebRequest As WebRequest
Public Shared allDone As New ManualResetEvent(False)
Private Shared BUFFER_SIZE As Integer = 1024
Public Class RequestState
' This class stores the state of the request
Private Shared BUFFER_SIZE As Integer = 1024
Public requestData As StringBuilder
Public bufferRead() As Byte
Public request As WebRequest
Public response As WebResponse
Public responseStream As Stream
Public Sub New()
bufferRead = New Byte(BUFFER_SIZE) {}
requestData = New StringBuilder("")
request = Nothing
responseStream = Nothing
End Sub ' New
End Class ' RequestState
Public Sub GetData(Sender As Object, Args As System.EventArgs)
lblResult.Text += "1"
myWebRequest = WebRequest.Create(dataURL)
Dim myRequestState As New RequestState()
myRequestState.request = myWebRequest
' Start the asynchronous request.
Dim asyncResult As IAsyncResult = CType(myWebRequest.BeginGetResponse(AddressOf RespCallback, myRequestState), IAsyncResult)
lblResult.Text += "2"
allDone.WaitOne()
End Sub
Private Sub RespCallback(asynchronousResult As IAsyncResult)
lblResult.Text += "3"
allDone.Set()
End Sub
回答1:
I don't know VB so it's hard to read for me but I'm suspecting GetData
is your onClick
handler.
First thing that is not right is that you have Shared
members. Why your reset event is Shared
? It makes all requests use the same object.
Basically Your code with ManualResetEvent
won't work because after first allDone.Set()
, your object remains set (as long as web application lives). To get "123" every time you should add allDone.Reset()
after allDone.WaitOne()
.
In Your situation web request returns to client before RespCallback
is called every time except first call (when your reset event is in non-signaled state).
AutoResetEvent
resets automatically. That's why it worked.
But! You can't do this this way. Making your ResetEvent
Shared
you make all request use the same object. When more than one request will be processed by your application at the same time you will get undetermined behavior.
Remove Shared from your code. Than your code will work (but not asynchronously) without allDone.Reset() and without AutoResetEvent. But it will provide known results (not depending on amount of requests).
About asynchronous call (now that we have code "working"). Well. There is no async request to your web page. allDone.WaitOne()
waits until your async webRequest finish. So basically you could just as well do synchronous request.
You need a special pattern for asynchronous web pages. You can read how to do this here.
But i'm not sure it's what you wanted. Do you want your request to be called asynchronously so that it will not use server resources or do you want to display some message to the user (like "Data is being downloaded...") while your web page will remain fully responsible?
If it's the second one you should use AJAX functionality (Like UpdatePanel
or using JavaScript directly). You can read about it here.
回答2:
Couple things to check:
- If your label is a fixed width, then it's possible the text is being clipped
- If you are using an UpdatePanel, you will need to set its mode to 'Conditional' and call
Update()
on it in the RespCallback callback method so that the UI gets refreshed with the latest label text value.
来源:https://stackoverflow.com/questions/10787825/webrequest-async-callback-code-only-gets-call-the-first-time