我有这个冻结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
我认为task.run
解决了这个问题,因为它创建了一个与UI线程分开的新线程,这段代码出了什么问题?
答案 0 :(得分: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应用程序,则可以使用Await
和HttpClient
来异步调用它。
答案 1 :(得分:0)
您必须等待对ValidateUrlContentAsnc的调用。将其转换为函数并返回任务。