我有一个vs2010,4.0 vb.net,WinForms应用程序在表单加载事件上调用AttemptLogin。 我希望尽可能避免阻止表单加载,我希望4.0中的任务和继续内容将是正确的方法,因为我可以在默认调度程序上运行主任务并继续oncurrentsynchronisationcontext但是我已经有了OnAttemptLogin工作我无法在继续调用中获取OnAttemptLoginCompleted函数。
我认为这是因为OnAttemptLogin返回“RunToCompletion”任务,因此永远不会调用continuation。但是我不知道如何处理这个问题,我尝试了很多东西,但是我现在已经把自己弄得很困惑了,所以我几乎把关键变得很糟糕。有人可以提供任何建议吗?我只是做错了还是我一起得到了错误的想法?
这就是我到目前为止,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
答案 0 :(得分:1)
这里的问题是......令人费解。你在这里遇到的主要问题是UITask不能运行的原因,因为LongRunningTask不是Task(Of HttpResponseMessage)类型。它实际上是一个Task(Of Task(Of HttpResponseMessage))。 OnAttempLogin()返回一个Task(H ...),但是你在表单加载中启动的任务是一个将返回该Task的Task,因此,Task(Of Task(Of ...))。因此该行中存在异常,因此UITask行永远不会运行。所以代码的问题在于,到处都有太多的Task事物。
另一个问题是你并没有真正做任何异步的事情(除了那个从未运行过的部分),因为你是Wait() - 执行所有任务。因此,您需要摆脱大部分等待才能真正实现这一目标。摆脱等待意味着你需要继续处理异常。
一些小问题:
以下是我认为新代码的样子。可能存在一些语法问题,因为我遗漏了一些要编译的东西:
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
答案 1 :(得分:1)
我的解决方案是删除所有内容并放弃,我将使用别的东西,其他任何东西,pff在这一点上锁定ui而不在乎,这三天垃圾是疯了。
将jtseng的回复标记为正确,即使它没有工作,因为他是唯一的回复,并且值得花时间去尝试和帮助。