[英]How can I continue execution of a catch block when the user enters credentials, from an exception caused by a credentials popup appears?
我制作了一个Winforms应用程序,该应用程序访问另一个服务器(在另一个活动目录域中)上的文件夹。 从文件夹中获取所有目录的行,但有时可能会失败,因为未保存访问文件夹的凭据(基本身份验证),因此基本身份验证对话框一次又一次弹出,从而破坏了系统。
在相应的catch块中,在用户输入其凭据然后重试相应的代码之后,如何通过恢复catch块的执行来处理该问题?
谢谢
通常最好让异常传播到UI,然后将问题报告给用户。 然后,用户可以决定重试该操作。 当然,这假定可以还原系统的状态。 如果可以以可以恢复系统状态的方式对操作进行编码,那将是最好的,因为这样,在存在其他异常的情况下,该操作也会很健壮。
如果重试必须从异常的角度继续进行,那么最好的选择可能是将该步骤放在一个循环中,如下所示:
private const int maxRetryAttempts = 3;
private static MyData ReadDataFile(string path)
{
int remainingAttempts = maxRetryAttempts;
while (true)
{
try
{
return ReadDataFileCore(path);
}
catch(UnauthorizedAccessException ex)
{
if (remainingAttemtps <= 0)
throw;
remainingAttempts--;
MessageBox.Show(ex.Message);
}
}
}
一会儿的原因(正确)
while(true){...}
语句可能看起来有些奇怪,但是在这种情况下是必须的。 它不是一个无限循环,因为该方法将在指定的迭代次数内返回值或引发异常。
通常,您会期望一个带有非恒定控制表达式的循环。
private static MyData ReadDataFile(string path)
{
int remainingAttempts = maxRetryAttempts;
while(remainingAttempts > 0) // Non-constant expression.
{
...
}
} // Compile error - Not all code paths return a value.
为了满足编译器的可达性检测器,未在此方法中执行此操作。 编译器将在while语句中看到常量true,并且知道while之后的语句不可访问,因此,方法的末尾不可访问。 如果选择了非常量,则必须在循环后放置代码以返回值或引发异常。 让我们考虑每个选项。
private static MyData ReadDataFile(string path)
{
int remainingAttempts = maxRetryAttempts;
while(remainingAttempts > 0)
{
...
}
return null;
}
我们可以返回一个空值(或其他错误指示符),在这种情况下,调用代码将必须期望空值并对其进行处理。 在我看来,这似乎是一个笨拙的设计。 我宁愿保证,如果该方法返回,那么它将返回一个好的值。
private static MyData ReadDataFile(string path)
{
int remainingAttempts = maxRetryAttempts;
while(remainingAttempts > 0)
{
...
}
throw new UnauthroizedAccessException(); // This exception does not contain any good debugging data.
}
另一种选择是在方法末尾引发异常。 这是一个合理的选择,但不是理想的选择。 如果我们创建一个新的异常,那么它几乎肯定比起最初导致问题的问题(已经被捕获并丢弃)的意义要小。
假设我们保存原始异常。
private static MyData ReadDataFile(string path)
{
UnauthorizedAccessException exception = null;
for (int attemptCount = 0; attemptCount < maxRetryAttempts; attemptCount++)
{
try
{
return ReadDataFileCore(path);
}
catch(UnauthorizedAccessException ex)
{
exception = ex;
MessageBox.Show(ex.Message);
}
}
throw exception; // The StackTrace gets replaced to indicate this line of code.
}
我们可以通过在方法顶部创建一个Exception变量并将捕获的异常存储在其中来重新抛出捕获的异常。 这样做的问题是它将导致堆栈跟踪被替换,并且将来使调试该应用程序变得更加困难。 最好通过使用throw;
来让异常保持不变throw;
重新抛出原始异常(只能在catch
块中发生,而不能在方法末尾发生)。
因此,在所有可用的替代方法中,我认为while(true)
是最佳选择,因为它可以确保控件将为该方法保留良好的数据或未损坏的异常。
请注意,如果该方法没有返回值( void
),那么可达性问题就消失了,但逻辑上就没有了。 我们仍然必须处理方法退出的问题,而不必执行应做的事情。
private static void ReadDataFile(string path)
{
for (int attemptCount = 0; attemptCount < maxRetryAttempts; attemptCount++)
{
try
{
ReadDataFileCore(path);
}
catch(UnauthorizedAccessException ex)
{
MessageBox.Show(ex.Message);
}
}
// Compiles justs fine, but did we actually read the data file?
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.