在PostAsJsonAsyc之后继续

时间:2013-06-22 20:56:04

标签: vb.net asynchronous .net-4.0

我有一个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

2 个答案:

答案 0 :(得分:1)

这里的问题是......令人费解。你在这里遇到的主要问题是UITask不能运行的原因,因为LongRunningTask不是Task(Of HttpResponseMessage)类型。它实际上是一个Task(Of Task(Of HttpResponseMessage))。 OnAttempLogin()返回一个Task(H ...),但是你在表单加载中启动的任务是一个将返回该Task的Task,因此,Task(Of Task(Of ...))。因此该行中存在异常,因此UITask行永远不会运行。所以代码的问题在于,到处都有太多的Task事物。

另一个问题是你并没有真正做任何异步的事情(除了那个从未运行过的部分),因为你是Wait() - 执行所有任务。因此,您需要摆脱大部分等待才能真正实现这一目标。摆脱等待意味着你需要继续处理异常。

一些小问题:

  • 你也不需要调度程序。
  • UITask只是一个Task,而不是Task(Of ...),因为它不会返回任何内容。
  • 我继续从UITask处理异常,以便它也捕获UITask的异常。如果我从LongRunningTask继续,我会想念那些例外。

以下是我认为新代码的样子。可能存在一些语法问题,因为我遗漏了一些要编译的东西:

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的回复标记为正确,即使它没有工作,因为他是唯一的回复,并且值得花时间去尝试和帮助。