【问题标题】:WebRequest Async CallBack Code only gets call the first timeWebRequest 异步回调代码仅在第一次被调用
【发布时间】:2012-05-28 16:33:12
【问题描述】:

我是 ASP.net (VB) 的绝对初学者。如果问题对有经验的成员来说太明显,请原谅我。

我尝试在异步模式下创建一个简单的 WebRequest,以防目标 URL 需要很长时间才能提供数据。在下面的代码中,我只想查看是否每次都正确调用了回调块(RespCallback)。如果一切顺利,每次单击调用“GetData”子的按钮时,lblResult 都应该附加字符串“123”。

但是,lblResult 仅在第一次单击后显示 123。在随后的单击之后,lblResult 只附加了“12”,就好像永远不会调用 RespCallback。当我尝试在 Visual Studio 中对此进行调试时,执行实际上直接进入了 RespCallback 部分,并且 lblResult.Text 手表实际上显示了“123123”,但生成的网页始终只显示“12312”

我确定我在这里遗漏了一些基本的东西,但我就是不知道是什么。我什至猜测它与浏览器缓存有关(因此结果第二次更改)但我也不知道如何解决。

有人可以帮忙吗?提前致谢。

吉姆

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

【问题讨论】:

  • 听起来很傻,但也许您的标签实际上包含“123123”,但布局正在被修剪,您只是看不到完整的价值?

标签: asp.net vb.net asynchronous webrequest


【解决方案1】:

我不懂 VB,所以我很难读懂,但我怀疑 GetData 是你的 onClick 处理程序。

首先不正确的是您拥有Shared 成员。为什么你的重置事件是Shared?它使所有请求都使用相同的对象。 基本上你的ManualResetEvent 代码将不起作用,因为在第一个allDone.Set() 之后,你的对象保持设置(只要Web 应用程序存在)。每次要获得“123”,您应该在allDone.WaitOne() 之后添加allDone.Reset()。 在您的情况下,Web 请求在每次调用 RespCallback 之前返回到客户端,除了第一次调用(当您的重置事件处于非信号状态时)。 AutoResetEvent 自动重置。这就是它起作用的原因。

但是!你不能这样做。使您的 ResetEvent Shared 使所有请求使用相同的对象。当您的应用程序将同时处理多个请求时,您将获得未确定的行为。

从您的代码中删除 Shared。在没有 allDone.Reset() 和 AutoResetEvent 的情况下,您的代码将工作(但不是异步)。但它会提供已知的结果(不取决于请求的数量)。

关于异步调用(现在我们的代码“工作”了)。好。您的网页没有异步请求。 allDone.WaitOne() 等到您的异步 webRequest 完成。所以基本上你也可以做同步请求。

您需要一种用于异步网页的特殊模式。你可以阅读如何做到这一点here

但我不确定这是你想要的。您是否希望异步调用您的请求,以便它不会使用服务器资源,或者您是否想向用户显示一些消息(例如“正在下载数据...”),而您的网页仍将完全负责?

如果是第二个,您应该使用 AJAX 功能(如 UpdatePanel 或直接使用 JavaScript)。你可以阅读它here

【讨论】:

  • 谢谢 Grzegorz。我已经听从了你的建议,现在我每次都得到“123”。我对这整个异步事情还是有点陌生​​,并且仍然不明白在这种情况下 WaitOne() 会为我做什么,如果我不打算得到任何异步的话?但是在原始问题的范围内,您已经完全回答了问题。我还不能投票给你的答案,因为我对董事会太陌生了。会继续努力。
【解决方案2】:

需要检查的几件事:

  1. 如果您的标签是固定宽度的,那么文本可能被剪裁了
  2. 如果您使用的是 UpdatePanel,则需要将其模式设置为“条件”并在 RespCallback 回调方法中对其调用 Update(),以便使用最新的标签文本值刷新 UI。

【讨论】:

  • 感谢 cmets,Grzegorz Wilczura 和 Jeremy。我检查了控件并确保标签不是固定宽度。我可以继续按下按钮,标签会多次附加 12 12 12(而不是 123 123。)
  • 另外,我使用的是 ASP:Label,而不是 TextBox 或 UpdatePanel。我还尝试将其更改为 TextBox 以进行测试,并产生了相同的结果。这些控件嵌套在 asp:Content 下,但我认为这无关紧要。
  • 一个观察结果是,服务器可能不会等待回调将 label.Text 值提供给浏览器。也许他们在不等待的单独线程上?我这样说是因为我只有在第一次按下按钮时才会得到 123。我怀疑我得到'123'的时间是Web服务器在页面被提供给浏览器之前足够快地响应答案的时间(当回调代码已经将label.Text值更改为'123'时)其他时候 label.Text 的值仍然是 '12' 并且页面在回调代码运行之前得到服务。
  • 我走得更远了。我将第 3 行的 ManualResetEvent(False) 更改为 AutoResetEvent(False)。现在我每次都得到123。但这并不能完全解决我的问题。对 Web 服务的调用现在是“异步”的。但是在我等待呼叫时 GUI 没有更新。换句话说,123 将同时出现,而不是在回调发生时 12 和 3。有人可以说明我在等待回调时如何更新 GUI(或执行其他任务)(这是开始这样做的重点。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-25
  • 2015-12-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多