0

我有一个 vs2010、4.0 vb.net、WinForms 应用程序在表单加载事件上调用 AttemptLogin。如果可能的话,我想避免阻止表单加载,我希望 4.0 中的任务和延续内容是正确的方法,因为我可以在默认调度程序上运行主要任务,并在 fromcurrentsynchronisationcontext 上继续运行,但是虽然我有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
4

2 回答 2

1

我的解决方案是删除所有内容并放弃,我将使用其他东西,其他任何东西,pff此时会锁定ui并且不在乎,三天的垃圾是疯狂的。

将 jtseng 的回复标记为正确,即使它不是唯一的回复,也值得花时间尝试和帮助。

于 2013-06-24T16:21:38.647 回答
1

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

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

一些小点:

  • 你也不需要调度器的东西。
  • UITask 只是一个任务,而不是一个 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
于 2013-06-23T16:09:25.660 回答