在异步方法

时间:2017-06-01 16:38:00

标签: asp.net vb.net asynchronous

我发布了上一个问题(asp.net UpdatePanel with UserControls and Page Level Async Method),并认为我已将问题缩小到另一个问题。

我有一个asp.net页面,需要从库中调用异步方法。

我按如下方式加载页面:

Private _dlgt As AsyncTaskDelegate
Protected Delegate Sub AsyncTaskDelegate()

 Protected Sub Page_Load(ByVal sender As Object, ByVal e As 
    Dim LoadTask As New PageAsyncTask(AddressOf OnBegin, AddressOf OnEnd, AddressOf OnTimeout, "AsyncTask1", True)
    Page.RegisterAsyncTask(LoadTask)
End Sub

Public Function OnBegin(ByVal sender As Object, ByVal e As EventArgs, ByVal cb As AsyncCallback, ByVal extraData As Object) As IAsyncResult
    _dlgt = New AsyncTaskDelegate(AddressOf Update)
    Dim result As IAsyncResult = _dlgt.BeginInvoke(cb, extraData)
    Return result
End Function

Private Async Function Update() As Task
    Dim AController As New CIP_WS.ARFController
    Dim ARFTask As Task(Of CIP_WS.ARF) = AController.GetARFWithResultsAsync(Client.ClientID, PRN, Nothing, StartTime, EndTime, CIP_WS.LabResultController.InequalityModes.AsIs)
    ARF = Await ARFTask
    PrintResults()
End Function

问题(我认为)是我必须将page属性设置为async = true,因为我需要等待任务。但是(根据MS),如果我将属性设置为true,则将异步处理整个页面。如果设置为false,"执行页面的线程将被阻塞,直到所有异步任务完成为止#34;。后者是我需要的,因为它是在数据之前(即在更新异步方法返回之前)加载和显示页面,而我只获得占位符。

要清楚,Update方法永远不会完成。 Page_Load总是在不等待方法完成的情况下完成。

我感觉如此接近,但现在却让它开始工作了。任何帮助,非常感谢。

EDIT ____

首先感谢到目前为止的回复。

我之前尝试过以下代码,但90%有效,但感谢您的建议。

    Dim LoadTask As New PageAsyncTask(AddressOf Update)
    Page.RegisterAsyncTask(LoadTask)

这可能是我自己的错,但我一直试图让问题变得简单,但它比这还要大。

上面的代码只有90%有效,因为它加载了异步数据,然后页面呈现并按预期加载。但是,我有一些动态的用户控件,它们最初也可以正常加载,但在回发期间行为不正确。在这种情况下,当用户单击按钮时,它不会更改特定用户控件中面板的可见性。我已经在上面的另一个SO问题的链接上完整地记录了这个问题,但简而言之,当我不使用异步时它可以正常工作,但在加载期间我没有异步调用时则不行。

我转到项目的另一部分,而我从这个问题中休息了一下,并开始异步访问网站的另一部分。再次,我点击了更多动态用户控件,但这次异步调用是在用户控件的加载而不是页面。我有完全相同的问题,除了下拉不是持久的选择,而不是面板可见性不持久。我想我需要以下列方式调用asyn方法

 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    Dim LoadTask As New PageAsyncTask(AddressOf OnBegin, AddressOf OnEnd, AddressOf OnTimeout, "AsyncTask1", True)
            Dim LoadTask As New PageAsyncTask(AddressOf OnBegin, AddressOf OnEnd, AddressOf OnTimeout, "AsyncTask1", True)

    Page.RegisterAsyncTask(LoadTask)
    Page.ExecuteRegisteredAsyncTasks()

    PrintGraph()

    End If 
  End Sub

它是手动传递true以强制并行处理,并调用ExecuteRegisteredAsyncTasks来修复cuser-ontrols和整个页面。它现在完美地异步。我必须做的唯一额外的事情,这会影响项目中的其他异步调用,将以下内容添加到配置中:

    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="false" />

唯一令人沮丧的是,我必须使用完全重载的方法(onLoad,OnEnd,OnTimeOut,State,Parallel)调用所有PageAsyncTask,而不是仅传递main方法。我认为由于必须在添加密钥后手动处理TimeOut,但我不确定。

Sooo ...然后我试着利用这些知识来帮助解决我的原始问题,但它仍然没有它!

所以我可以:

1)使用以下命令,加载数据异步,并最初加载页面,但任何回发都会将用户控件恢复为原始状态。这也会对我遇到的其他异步问题产生影响,这意味着所有未来的异步任务都需要按照第2项进行注册,因此这将重新打破现在正在工作的页面。

    Dim LoadTask As New PageAsyncTask(AddressOf Update)
    Page.RegisterAsyncTask(LoadTask)

2)使用以下内容,它不等待已注册的异步方法完成(据我所知),因此加载网页时基本上不更新任何控件。根据评论,我接受可能有其他错误,我没有做到。

     Protected Sub Page_Load(ByVal sender As Object, ByVal e As 
     Dim LoadTask As New PageAsyncTask(AddressOf OnBegin, AddressOf OnEnd, AddressOf OnTimeout, "AsyncTask1", True)
    Page.RegisterAsyncTask(LoadTask)
    End Sub

如果我不按照MS文档使用IAsyncResult方法,并且只是为OnBegin调用方法,那么我可以将此工作与第1项相同,但这仍然与1具有相同的问题。

     Protected Sub Page_Load(ByVal sender As Object, ByVal e As 
     Dim LoadTask As New PageAsyncTask(AddressOf Update, AddressOf OnEnd, AddressOf OnTimeout, "AsyncTask1", True)
    Page.RegisterAsyncTask(LoadTask)
    End Sub

应该注意我可以在用户控件调用异步加载方法的其他页面场景中成功使用IAsyncResult方法。

    Private _dlgt As AsyncTaskDelegate
    Protected Delegate Sub AsyncTaskDelegate()

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    Dim LoadTask As New PageAsyncTask(AddressOf OnBegin, AddressOf OnEnd, AddressOf OnTimeout, "AsyncTask1", True)

    Page.RegisterAsyncTask(LoadTask)
    Page.ExecuteRegisteredAsyncTasks()

    PrintGraph()

    End sub 


 Public Function OnBegin(ByVal sender As Object, ByVal e As EventArgs, ByVal cb As AsyncCallback, ByVal extraData As Object) As IAsyncResult

    _dlgt = New AsyncTaskDelegate(AddressOf ReLoadSelectors)
    Dim result As IAsyncResult = _dlgt.BeginInvoke(cb, extraData)

    Return result
End Function

`3)将数据同步加载,一切都恢复正常,包括用户控件保持其值,但只是死得很慢。

我想到了这个。对所有事情都很好地同步,只是不是异步。 Manged让它在一个页面上工作,其中用户控件需要执行异步加载调用,但无法使其在另一个页面上工作,页面必须执行异步加载调用。一种类型的任务注册等待异步数据方法返回,但使用IAsyncResult的完全重载版本不会。

如果有人能够发现我出错的地方,并让我摆脱痛苦,我会非常感激。

1 个答案:

答案 0 :(得分:1)

是的,您需要将Page.Async设置为true才能使用RegisterAsyncTask。所有注册的任务都保证在页面预呈现事件之前完成。

AsyncTaskDelegate的定义是什么?为什么不使用PageAsyncTask.ctor(Func处理程序)?像下面的东西。

w3p.exe