1

I have a login page in an ASP.Net web forms application. On successful login it does some time-consuming database operations which is slowing the login process, so I want to run these asynchronously.

I am trying to do this in the recommended way using RegisterAsyncTask, etc. I have set the @Page Async="true" in the aspx file and implemented the following code in the aspx.vb file (cut down to show the essential elements):

       Protected Sub btnLogin_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLogin.Click

            If LoginSuccessful() Then
               DoLoginStuff()
            End If

        End Sub

        Private Sub DoLoginStuff()
            ...
            RegisterAsyncTask(New PageAsyncTask(Function() DoExpensiveDbCheck(userKey)))
            Page.ExecuteRegisteredAsyncTasks()
            ...
        End Sub

        Private Async Function DoExpensiveDbCheck(ByVal UserKey As Integer) As Task
           ...
           response = Await Task.Run(Function() DbService.DoCheck(UserKey))
           If response.Success AndAlso response.Items.Count() = 1 Then
               Session("DbValueForUseLater") = response.Item[0].Whatever
           End If
        End Function

However the DoExpensiveDbCheck function never runs (a breakpoint at the start of the function is never hit), and the Session("DbValueForUseLater") is never set.

I thought maybe it doesn't run because the login function finishes by doing a redirect to the home page of the application, so I added the Page.ExecuteRegisteredAsyncTasks() just in case, but this makes no difference.

Interestingly if I create a Task for DoExpensiveDbCheck rather than using RegisterAsyncTask, and do a Wait on this Task then the application completely freezes, and again a breakpoint in DoExpensiveDbCheck is never hit.

Does anyone know what I am doing wrong here?

PRS
  • 741
  • 1
  • 7
  • 27
  • I might be wrong here, but I'm pretty sure the thread is fully removed when the page end and the data is sent. You could try [HostingEnvironment.QueueBackgroundWorkItem](https://msdn.microsoft.com/en-us/library/dn636893(v=vs.110).aspx) – the_lotus Aug 18 '17 at 12:23
  • Hi @the_lotus. I need this to run asynchronously but at some point within the page lifecycle because future pages may need to refer to Session("DbValueForUseLater"). It seems QueueBackgroundWorkItem queues something to run at any point before the app domain shutdown? – PRS Aug 18 '17 at 13:37
  • Are you only running the one async task? Using `PageAsyncTask` is useful if you have multiple async tasks that you want to run in *parallel* to speed up the time. It is not truly async as what you want it if I understand your scenario. It does not continue execution after starting the async task so you'll see no improvements to the time if it is just one async task. I think the only benefit of running one is that it frees the thread for IIS to handle other requests, not the current one. – singularhum Aug 19 '17 at 03:03
  • Hi @singularhum. Yes I was hoping it would run the DoExpensiveDbCheck asynchronously to everything else in DoLoginStuff(). So I take it I would need to put the rest of the processing in DoLoginStuff into a seperate async method and register that as well to get them to run asynchronously? I can try that, but there is also still a problem with the DoExpensiveDbCheck method never running at all. – PRS Aug 21 '17 at 09:13
  • Yeah you could give it a try but I'm quite unfamiliar with async so I don't know much more than what I mentioned. As for the issue, I'm not sure why but calling ExecuteRegisteredAsyncTasks seems to have no affect in your code. However, it is automatically called just before the PreRenderComplete event like it is supposed to, which explains why it never runs because I assume your redirect occurs before then. If you comment out your redirect you should see that it will eventually be executed. – singularhum Aug 21 '17 at 11:45

0 Answers0