我有一个vs2010,4.0 vb.net,在表单加载事件上调用AttemptLogin的WinForms应用程序。如果可能的话,我希望避免阻止表单加载,并且我希望4.0中的任务和继续操作是正确的,因为我可以在默认调度程序上运行主要任务,在当前同步上下文中继续运行,但是尽管我已经完成了OnAttemptLogin的工作,但我无法调用延续中的OnAttemptLoginCompleted函数。
我认为这是因为OnAttemptLogin返回一个"RunToCompletion“任务,这样就不会调用这个延续。但我不知道该如何处理,我尝试了很多事情,但我现在已经困惑自己了,我几乎要捣碎钥匙。有人能给我建议吗?我是做错了,还是一起搞错了?
到目前为止,OnAttemptLogin可以像我所期望的那样工作,但是它永远不会调用LongRunning任务的延续。
请注意:我不能使用等待,因为我在vs2010 .net4.0,所以我被ContinueWith困住了。
Public Sub AttemptLogin(OnAttemptLoginCompleted As Action(Of Task(Of HttpResponseMessage)))
Try
Dim LongRunningTask As Task(Of HttpResponseMessage) = Task.Factory.StartNew(Function()
Return OnAttemptLogin()
End Function, TaskScheduler.Default)
Dim UITask As Task(Of HttpResponseMessage) = LongRunningTask.ContinueWith(Sub(t)
OnAttemptLoginCompleted(t)
End Sub, TaskScheduler.FromCurrentSynchronizationContext)
LongRunningTask.Wait()
Catch ex As AggregateException
' nom nom nom
' do something useful
End Try
End Sub
Private Function OnAttemptLogin() As Task(Of HttpResponseMessage)
Dim aClient = New HttpClient()
Using (aClient)
' CREATE REQUEST
aClient.DefaultRequestHeaders.Accept.Add(New MediaTypeWithQualityHeaderValue("application/json"))
aClient.DefaultRequestHeaders.Add("Authorization", "Basic " + Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(String.Format("{0}:{1}", CallingDTO.Email, CallingDTO.Password))))
UserQueryDTO.UserName = UserDTO.Email
UserQueryDTO.Password = UserDTO.Password
Dim url As String = DnnRequest.GetUrl(Credentials.HttpAlias, cstModuleAssembly, "User", "CanLogin", False)
' POST REQUEST
Dim p As Task(Of HttpResponseMessage) = aClient.PostAsJsonAsync(url, UserQueryDTO).ContinueWith(Function(x)
' READ RESPONSE
Dim r = x.Result.Content.ReadAsAsync(Of HttpResponseMessage)()
r.Wait()
Return r.Result
End Function)
Try
p.Wait()
Catch ex As Exception
End Try
Return p
End Using
End Function发布于 2013-06-23 16:09:25
问题是..。纠结了。这里的主要问题,UITask不运行的原因,是因为LongRunningTask不是任务类型( HttpResponseMessage)。它实际上是一个任务(任务( HttpResponseMessage))。OnAttempLogin()返回一个任务(H.),但是在表单加载中启动的任务将返回该任务,因此返回任务(任务(.))。因此,该行中有一个异常,因此UITask行永远不会运行。所以代码的问题是到处都有太多的任务。
另一个问题是,您并没有真正异步地执行任何事情(除了从未运行的部分),因为对于所有的任务,您都在等待()-ing。因此,你需要摆脱大部分的等待,才能真正做到这一点。摆脱等待意味着您需要用一个延续来处理异常。
一些小问题:
下面是我认为新代码将是什么样子的一个例子。可能会有一些语法问题,因为我缺少一些东西来编译它:
Public Sub AttemptLogin(OnAttemptLoginCompleted As Action(Of Task(Of HttpResponseMessage)))
Dim LongRunningTask As Task(Of HttpResponseMessage) = OnAttemptLogin()
Dim UITask As Task = LongRunningTask.ContinueWith(AddressOf OnAttemptLoginCompleted)
uiTask.ContinueWith(Sub(t)
Dim ex As AggregateException = t.Exception
'nom nom nom
'all your exceptions will end up here.
End Sub, TaskContinuationOptions.OnlyOnFaulted)
End Sub
Private Function OnAttemptLogin() As Task(Of HttpResponseMessage)
Dim aClient = New HttpClient()
Using (aClient)
' CREATE REQUEST
aClient.DefaultRequestHeaders.Accept.Add(New MediaTypeWithQualityHeaderValue("application/json"))
aClient.DefaultRequestHeaders.Add("Authorization", "Basic " + Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(String.Format("{0}:{1}", CallingDTO.Email, CallingDTO.Password))))
UserQueryDTO.UserName = UserDTO.Email
UserQueryDTO.Password = UserDTO.Password
Dim url As String = DnnRequest.GetUrl(Credentials.HttpAlias, cstModuleAssembly, "User", "CanLogin", False)
' POST REQUEST
Dim p As Task(Of HttpResponseMessage) = aClient.PostAsJsonAsync(url, UserQueryDTO).ContinueWith(Function(x)
' READ RESPONSE
Dim r = x.Result.Content.ReadAsAsync(Of HttpResponseMessage)()
r.Wait()
Return r.Result
End Function)
Try
p.Wait()
Catch ex As Exception
End Try
Return p
End Using
End Function发布于 2013-06-24 16:21:38
我的解决方案是删除一切并放弃,我会使用其他的东西,任何其他的东西,在这一点上我锁定ui而不关心,三天在这个垃圾上是疯狂的。
尽管这并不是他唯一的回答,但他的回答是正确的,值得花点时间去尝试和帮助。
https://stackoverflow.com/questions/17255219
复制相似问题