使用Async-await时UI会冻结

Off*_*'er 3 vb.net asynchronous task-parallel-library async-await

我有这个功能冻结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
Run Code Online (Sandbox Code Playgroud)

我认为这task.run解决了这个问题,因为它创建了一个与UI线程分离的新线程,这段代码出了什么问题?

Ste*_*ary 7

该站出来给我的一件事是使用3种独立异步代码模式(Await,ContinueWith,和AsyncManager),而不是仅仅使用Await.

另一个重要的事情是你正在返回ActionResult- 表明这是一个ASP.NET应用程序 - 而且还在讨论"UI线程".有没有对ASP.NET UI线程.

因此,我重新解释"冻结UI"为"在处理程序完成之前不返回结果",这正是ASP.NET 应该如何工作的.

因此,首先,删除所有不必要的AsyncManager,ContinueWithTask.Run代码,从而真正简化方法:

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
Run Code Online (Sandbox Code Playgroud)

接下来,解决"冻结UI"问题.解决此问题的适当位置是在UI中,而不是在服务器(ASP.NET)端.防止UI冻结的方法是以异步方式调用服务器.如果UI是.NET应用程序,则可以使用Awaitwith HttpClient来异步调用它.