単一のメソッドでインターフェースを定義する外部フレームワークを使用しています。
bool Authenticate();
つまり、ユーザーインタラクション(WinForms)を含む、認証のプロセス全体が含まれます。私がやりたいことは次のようなものです:
bool Authenticate()
{
bool succeeded = false;
bool userCancelled = false;
while(!succeeded && !userCancelled)
{
var credentials = AskTheUserForCredentials(); // this needs to wait for user input before returning!
if (credentials == null)
userCancelled = true;
else
succeeded = AuthenticateWithAnExternalServer(credentials);
if (!succeeded)
ShowErrorMessage();
}
return succeeded;
}
これで、実装が簡単になり、AskTheUserForCredentials()
内部でShowErrorMessage()
使用することができます。Form.ShowDialog()
これは、実際の認証プロセスのダイアログが消え、新しい、クリックして閉じる必要のあるダイアログにエラーメッセージが表示されるため、ユーザーエクスペリエンスが非常に悪くなります。
むしろ、すべてを1つの形式で表示したいのですが、それは表示されたままで、テキストボックス/ボタンを適切に無効にし、エラーメッセージを単独で表示します。
この単一のブロッキングメソッド呼び出しでどのように実行しますか?
アップデート
これまでの最善の解決策は、内部にメッセージポンプを実装することですAskTheUserForCredentials()
。
Credentials AskTheUserForCredentials()
{
while(NeitherOkNorCancelPressed())
{
Application.DoEvents();
Thread.Sleep(10); // Standard Sleep(0) results in 100% procesor core usage.
}
return CreateCredentialsFromTextboxesEtc();
}
今、私たちは皆、メッセージポンプがきれいにはほど遠いことを知っています。
このソリューションは正確にどれほど悪いですか?
何か良いですか?
更新2
メッセージポンプにはいくつかの落とし穴がありました。
醜く、CPU効果が十分ではない
ホワイトUIAutomationでの動作が非常に遅い
最終的に、プロセス全体をChrisBDとしてダイアログに委任しました(ダイアログは、最終的に成功または失敗した後にのみ閉じます)。これは、IoCを使用してGUIから認証を抽象化するのに時間がかかりましたが、最終的にはクリーンで意図したとおりに機能します。