当用户输入凭据时,如何显示由凭据弹出引起的异常,我如何继续执行catch块? [英] How can I continue execution of a catch block when the user enters credentials, from an exception caused by a credentials popup appears?

查看:129
本文介绍了当用户输入凭据时,如何显示由凭据弹出引起的异常,我如何继续执行catch块?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我做了一个Winforms应用程序,它在另一个服务器(另一个活动目录域)中存放文件夹。从文件夹获取所有目录的行,但有时可能会因异常而失败,因为访问文件夹(基本身份验证)的凭据尚未保存,因此基本的auth对话框会一次又一次弹出,从而破坏系统。



在相应的catch块中,如何在用户输入他的凭据之后恢复执行catch块,然后重试相应的代码? p>

谢谢

解决方案

通常最好让异常传播到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);
}
}
}

(true)



while(true){...} 语句可能会看起来有点奇怪,但在这种情况下是必要的。它看起来不是一个无限循环,因为该方法将返回一个值或在指定的迭代次数内抛出异常。



通常,你会期望一个具有非常数控制表达式的循环。

  private static MyData ReadDataFile(string path)
{
int remainingAttempts = maxRetryAttempts;
while(remainingAttempts> 0)//非常数表达式。
{
...
}
} //编译错误 - 不是所有的代码路径都返回一个值。

为了满足编译器的可达性检测器,这种方法没有完成。编译器将在while语句中看到常量true,并且知道while之后的语句是不可达的,因此方法的结束是不可达的。如果选择了非常数,则代码将不得不放在循环之后返回值或抛出异常。让我们考虑每个选项。

  private static MyData ReadDataFile(string path)
{
int remainingAttempts = maxRetryAttempts;
while(remainingAttempts> 0)
{
...
}
返回null;
}

我们可以返回一个空值(或其他一些错误指示符),其中调用代码将不得不期望null值并处理它们。这似乎是一个笨重的设计给我。我宁愿保证,如果方法返回,那么它返回一个好的值。

  private static MyData ReadDataFile(string path )
{
int remainingAttempts = maxRetryAttempts;
while(remainingAttempts> 0)
{
...
}
throw new UnauthroizedAccessException(); //此异常不包含任何好的调试数据。
}

另一种替代方法是在方法结束时抛出异常。这是一个合理的选择,但并不理想。如果我们创建一个新的异常,那么它几乎肯定不如首先引起问题的那个有意义,而这已经被捕获和丢弃了。



假设我们保存原始异常。

  private static MyData ReadDataFile (string path)
{
UnauthorizedAccessException异常= null;
for(int attemptCount = 0; attemptCount< maxRetryAttempts; attemptCount ++)
{
try
{
return ReadDataFileCore(path);
}
catch(UnauthorizedAccessException ex)
{
exception = ex;
MessageBox.Show(ex.Message);
}
}
抛出异常; // StackTrace被替换以表示这一行代码。
}

我们可以重新抛出我们通过在顶部创建一个Exception变量来捕获的异常的方法并将捕获到的异常存储在其中。这样做的问题是它会导致堆栈跟踪被替换,并使将来更难调试应用程序。最好使用 throw; 重新抛出原始异常(只能在 catch 块,而不是方法的结尾。



所有可用的替代方案,我判断 while(true)是最好的选择,因为它保证控件将离开这个方法或者有良好的数据或不成功的异常。



请注意,如果方法有没有返回值( void ),那么可达性关系消失,但不是逻辑问题,我们仍然必须处理方法退出的问题,而不执行它应该这样做。

  private static void ReadDataFile(string path)
{
for(int attemptCount = 0; attemptCount< maxRetryAttempts; attemptCount ++)
{
try
{
ReadDataFileCore(path);
}
catch(UnauthorizedA ccessException ex)
{
MessageBox.Show(ex.Message);
}
}
//编译刚好,但是我们实际读取了数据文件吗?
}


I made a Winforms application, which acccesses folders on another server (in another active directory domain). The line of gets all directories from a folder, but it may sometimes fail with an exception because the credentials to access the folder (basic authentication) have not been saved, so the basic auth dialog box pops up again and again, breaking the system.

In the corresponding catch block, how could I handle this by resuming execution of the catch block after the user enters his or her credentials and then retry the corresponding code?

Thanks

解决方案

It is typically best to let the exception propogate up to the UI and then report the problem to the user. The user can then decide to retry the operation. This assumes, of course, that the state of the system can be restored. If it is possible to code the operation in such a way that the state of the system can be restored, then that is best, because then the operation will be robust in the presence of other exceptions as well.

If the retry must continue from the point of the exception, then your best bet is probably to put that step within a loop, like this:

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);
        }
    }
}

Reason for while(true)

The while(true){...} statement may look a little odd, but in this case it is necessary. It is not, as it appears, an infinite loop, since the method will either return a value or throw an exception within the specified number of iterations.

Normally, you would expect a loop with a non-constant controlling expression.

private static MyData ReadDataFile(string path)
{
    int remainingAttempts = maxRetryAttempts;
    while(remainingAttempts > 0)  //  Non-constant expression.
    {
        ...
    }
}  //  Compile error - Not all code paths return a value.

This was not done in this method in order to satisfy the compiler's reachability detector. The compiler will see the constant true in while statement and know that the statement after the while is not reachable and, therefore, the end of the method is not reachable. If a non-constant were chosen, then code would have to be placed after the loop to either return a value or throw an exception. Let's consider each of the options.

private static MyData ReadDataFile(string path)
{
    int remainingAttempts = maxRetryAttempts;
    while(remainingAttempts > 0)
    {
        ...
    }
    return null;
}  

We could return a null value (or some other error indicator), in which case the calling code would have to expect null values and handle them. This seemed like a clunky design to me. I would rather be guaranteed that, if the method returns, then it returns a good value.

private static MyData ReadDataFile(string path)
{
    int remainingAttempts = maxRetryAttempts;
    while(remainingAttempts > 0)
    {
        ...
    }
    throw new UnauthroizedAccessException();  // This exception does not contain any good debugging data.
}  

The other alternative is to throw an exception at the end of the method. This is a reasonable option, but it is not ideal. If we create a new exception, then it would almost certainly be less meaningful than the one that caused the problem in the first place, which was already caught and discarded.

Suppose we save the original exception.

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.
}

We could rethrow the exception that we caught by creating an Exception variable at the top of the method and storing the caught exception in it. The problem with this is it will cause the stack trace to be replaced and make it harder to debug the application in the future. It is best to just let the exception propogate up unchanged by using throw; to rethrow the original exception (which can only happen in the catch block, not at the end of the method.

So of all the alternatives available, I judged while(true) to be the best option, because it guarantees that control will leave this method either with good data or an uncorrupted exception.

Note that if the method had no return value (void), then the reachability concerns vanish, but not the logical concerns. We would still have to deal with the issue of the method exiting without having performed what it was supposed to do.

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? 
}

这篇关于当用户输入凭据时,如何显示由凭据弹出引起的异常,我如何继续执行catch块?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆