2016-06-28 18 views
1

私は以下を実装する必要があります:ユーザーが電子メールを入力するページがあります。テキストが変わるたびに、ユーザーがDBに存在するかどうかをチェックし、その情報に基づいてボタンのテキストを「サインアップ」または「サインイン」に設定する必要があります。問題は、このDBリクエストには数秒かかることがある(理由は無関係です)APIは非同期なので、イベントハンドラはasyncで装飾され、メールエントリは何度か変更される可能性があるため、このハンドラはいくつか呼び出されますいずれかが終了する前に時間。だから私は同時のAPI要求をして、潜在的に、ボタンのテキストを変更しようと同時に試み、それはうまく終了しないことがあります。私はこのような何かを考えた:電子メール検証ロジックを実装して非同期化する方法は?

private async void OnTextChanged(object sender, TextChangedEventArgs e) 
{ 
    mailEntry.TextChanged -= OnTextChanged; 
    ... 
     submitButton.Text = (await api.AccountExistAsync(mailEntry.Text)).IsRegistered 
          ? "Sign in" 
          : "Sign up"; 
    ... 
    mailEntry.TextChanged += OnTextChanged; 
} 

しかし、この設計の問題は、たとえば、有効な電子メールは、それがチェックれることは決してないだろう。その場合には、-= OnTextChanged+= OnTextChangedの間で入力された、ということです。

私の質問は、達成しようとしていることを実装する正しい方法は何ですか?前もって感謝します。

private long requestNumber; 

private async void OnTextChanged(object sender, TextChangedEventArgs e) 
{ 
    var text = mailEntry.Text; 

    long myRequestNumber = ++requestNumber; 

    await Task.Delay(200); 

    if (requestNumber != myRequestNumber) 
     return; 

    var result = (await api.AccountExistAsync(text)).IsRegistered; 

    if (requestNumber != myRequestNumber) 
     return; 

    submitButton.Text = result ? "Sign in" : "Sign up"; 
} 

は、それはあなたがテキストを変更するたびにインクリメントされ、最後のリクエスト数を保持するrequestNumber変数を維持します。

+0

検証中にユーザーがテキストを編集しないようにしますか?または、新しいリクエストが発行されたときに現在のリクエストをキャンセルしますか? –

+0

私は、ユーザーがテキストを入力することを防止したくないと確信していますが、ユーザーは要求に気を付けるべきではありません。 – nicks

+0

この妥当性チェックを行うにはより良い方法があると確信しています。テキストの変更は問題ではありません。あなたが現在isValid Userかどうかをチェックしているかどうかを示すことができますか?Submitでこのタイプのものをチェックする必要があります。 – MethodMan

答えて

0

は、ここに1つのソリューションです。

AccountExistAsync操作の完了後、コードが変数が変更されたことが判明した場合、新しい要求が発行されたと判断し、UIを更新しません。

解決策は、検証要求を送信する前に200ミリ秒待機します。これにより、検証操作が200ミリ秒遅れることになりますが、特にユーザーが迅速に入力しているときに、送信されるリクエストが多すぎるのを防ぎます。これはもちろんオプションです。

編集: requestNumberを更新/読み取り時にこのようなコードにのみUIスレッドで実行されるため、私は同期の使用を削除しました。

+0

が魅力のように働いたとは思わない。しかし、私はあなたがロックを解除した理由を理解できませんが、イベントが同時に処理される可能性はありませんか? – nicks

+1

'await'の前と後(UIイベントハンドラ内)のコードは、(ConfigureAwait(false)'をしない限り)UIスレッドで実行されるため、単一のスレッドです。 –

+0

@NikaGamkrelidze、私は、最初に 'mailEntry.Text'をキャプチャすることは重要ではないことに気付きました。なぜなら、新しいリクエストが発行されなかった場合にのみ値を読み込むからです。エミュレータによるテストが失敗する原因となった問題は何ですか? –

関連する問題