使用异步等待时,用户界面会冻结

3

我有一个冻结用户界面的函数:

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

我认为task.run可以解决这个问题,因为它会创建一个新的线程并与UI线程分离,但是这段代码有什么问题?
2个回答

7
有一件事情引起了我的注意,就是使用了三种不同的异步代码模式(Await、ContinueWith和AsyncManager),而不是只使用Await。
另一个主要问题是返回了ActionResult - 表示这是一个ASP.NET应用程序 - 但却谈论了“UI线程”。在ASP.NET上根本没有UI线程。
因此,我重新解释“冻结UI”为“在处理程序完成之前不返回结果”,这正是ASP.NET应该工作的方式。
所以,首先删除所有不必要的AsyncManager、ContinueWith和Task.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

接下来,解决“冻结UI”的问题。解决这个问题的正确位置是在UI中,而不是在服务器(ASP.NET)端。防止UI冻结的方法是以异步方式调用服务器。如果您的UI是.NET应用程序,可以使用AwaitHttpClient以异步方式调用它。


1
惊人的心灵诊断。因此加一分。让我们看看它是否会成真。 - usr
1
@OffirPe'er:我有一篇异步介绍,可能会有所帮助,并在结尾提供了良好的后续资源。关于async:true AJAX调用,这是JavaScript中“以异步方式调用服务器”的等效方法。 - Stephen Cleary

0

你必须等待调用ValidateUrlContentAsnc后再将其转换为一个函数并返回Task。


1
那并没有解释阻塞。 - usr
@usr 你是对的。一定是 Increment() 在阻塞。 - Crowcoder
2
我认为有些东西正在阻塞,而且在发布的代码中看不到。对于await问题来说,这并不罕见。通常,await的用户甚至不知道足够的信息来发布相关的代码。 - usr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接