0

フォームの読み込みイベントで AttemptLogin を呼び出す vs2010、4.0 vb.net、WinForms アプリがあります。可能であればフォームの読み込みをブロックしないようにしたいのですが、4.0 のタスクと継続が正しい方法になることを望んでいました。メイン タスクをデフォルト スケジューラで実行し、継続を fromcurrentsynchronisationcontext で実行できるからです。 OnAttemptLogin が機能している 継続で OnAttemptLoginCompleted 関数を呼び出すことができません。

OnAttemptLogin が「RunToCompletion」タスクを返すため、継続が呼び出されないためだと思います。しかし、私はそれに対処する方法がわかりません。私は多くのことを試しましたが、今では自分自身を混乱させてしまい、ほとんどキーをマッシュアップしています. 誰でもアドバイスを提供できますか?私は単に間違っているのでしょうか、それとも間違った考えを持っているのでしょうか?

これまでのところ、OnAttemptLogin は期待どおりに機能しますが、LongRunning タスクの継続を呼び出すことはありません。

注意してください:vs2010 .net4.0にいるのでawaitを使用できないため、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

ここでの問題は...複雑です。ここでの主な問題、UITask が実行されない理由は、LongRunningTask が Task(Of HttpResponseMessage) 型ではないためです。実際には Task(Of Task(Of HttpResponseMessage)) です。OnAttempLogin() は Task(of H...) を返しますが、フォーム ロードで開始するタスクはその Task を返す Task であるため、Task(Of Task(Of ...)) になります。したがって、その行には例外があるため、UITask 行は実行されません。したがって、コードの問題は、いたるところにタスクが多すぎることです。

もう 1 つの問題は、すべてのタスクに対して 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
于 2013-06-23T16:09:25.660 に答える