我正在使用一个外部框架,该框架用一个方法定义了一个接口:
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()
内部使用。这是非常糟糕的用户体验,因为实际身份验证过程的对话框消失了,并且错误消息出现在一个新的、必须单击以关闭对话框中。
我宁愿将它全部放在一个表单中,保持可见,适当地禁用文本框/按钮并自行显示错误消息。
在这个单一的阻塞方法调用中,您将如何做到这一点?
更新
迄今为止最好的解决方案是在内部实现一个消息泵AskTheUserForCredentials()
:
Credentials AskTheUserForCredentials()
{
while(NeitherOkNorCancelPressed())
{
Application.DoEvents();
Thread.Sleep(10); // Standard Sleep(0) results in 100% procesor core usage.
}
return CreateCredentialsFromTextboxesEtc();
}
现在我们都知道消息泵远非干净。
这个解决方案到底有多糟糕?
有更好的吗?
更新 2
消息泵有一些陷阱:
丑陋且不完全使用 CPU
使用 White UIAutomation 工作非常缓慢
我最终将整个过程委托给了 ChrisBD 的对话(对话仅在最终成功或失败后关闭)。这需要更多时间来使用 IoC 将身份验证从 GUI 中抽象出来,但最终是干净的并且可以按预期工作。