Offir
Offir

Reputation: 3491

UI freezes when using Async-await

I have got this function which freezes the UI:

Public Sub ValidateUrlContentAsync(externalApplyURL As String)

    AsyncManager.OutstandingOperations.Increment()

    Dim result = Threading.Tasks.Task.
        Run( _
            Async Function()
                Return Await ValidateLinks.ValidateUrlContentAsync(externalApplyURL)
            End Function).
        ContinueWith(
            Sub(t)
                Try
                    If t.IsFaulted Then
                        Throw t.Exception
                    End If

                    If t.Result.Error IsNot Nothing Then
                        ErrorHandler.Log.Warn(
                            String.Format("ValidationError: {0}, Exception: {1}", externalApplyURL, t.Result.Error))
                    End If

                    AsyncManager.Parameters("validationResult") = t.Result.ResultValue.ToString()

                Finally
                    AsyncManager.OutstandingOperations.Decrement()
                End Try

            End Sub)

End Sub

 Public Function ValidateUrlContentCompleted(validationResult As String) As ActionResult

    Return Json(validationResult, JsonRequestBehavior.AllowGet)

End Function

I thought that task.run solves this issue because it creates a new thread separated from the UI thread, What's wrong with this code?

Upvotes: 3

Views: 1305

Answers (2)

Stephen Cleary
Stephen Cleary

Reputation: 456322

One thing that stands out to me is the use of three separate asynchronous code patterns (Await, ContinueWith, and AsyncManager) instead of just using Await.

The other major thing is that you're returning an ActionResult - indicating this is an ASP.NET application - and yet talking about a "UI thread". There is no UI thread on ASP.NET.

Thus, I reinterpret "freezes the UI" as "does not return a result until the handler is complete", which is exactly how ASP.NET is supposed to work.

So, first, remove all the unnecessary AsyncManager, ContinueWith, and Task.Run code, which really simplifies the method:

Public Function ValidateUrlContent(externalApplyURL As String) As Task(Of ActionResult)
  Dim result = Await ValidateLinks.ValidateUrlContentAsync(externalApplyURL)
  If result.Error IsNot Nothing Then
    ErrorHandler.Log.Warn(String.Format("ValidationError: {0}, Exception: {1}", externalApplyURL, result.Error))
  End If
  Return Json(result.ResultValue.ToString(), JsonRequestBehavior.AllowGet)
End Function

Next, solve the "freezing the UI" problem. The proper place to solve this problem is in the UI, not on the server (ASP.NET) side. The way to prevent the UI from freezing is to call the server in an asynchronous way. If you UI is a .NET application, you can use Await with HttpClient to call it asynchronously.

Upvotes: 7

Crowcoder
Crowcoder

Reputation: 11514

You must Await the call to ValidateUrlContentAsnc. Turn it into a Function and return Task.

Upvotes: 0

Related Questions