【问题标题】:C# - windows form - how to catch an unhandled exception from a taskC# - Windows 窗体 - 如何从任务中捕获未处理的异常
【发布时间】:2016-03-11 16:17:02
【问题描述】:

我正在使用 BCrypt Nuget 包创建一个带有一些加密的 Windows 窗体应用程序。该包使用“验证”方法来检查密码和哈希。如果密码和哈希匹配,则“验证”方法返回 true。我正在尝试通过在调用“验证”方法时执行一些操作来向表单添加一些功能。

所以我将它用作一项任务,当我使用以“$2$”开头的正确 bcrypt 哈希作为比较的输入时,代码工作正常。但是当给出随机输入时,包识别出无效的盐并且包抛出 saltParseException,程序崩溃并显示异常未处理的错误。我尝试添加 saltParaseException 处理,但仍然无法正常工作。

private void btncheckPassword_Click(object sender, EventArgs e)
    {
        bool isMatch = false;
        if(txtPlainPasswordCheck.TextLength > 0 && txtHashedPasswordCheck.TextLength > 0)
        {
            try
            {
              var Task_VerifyPassword = Task.Factory.StartNew(() => BCrypt.Net.BCrypt.Verify((String)txtPlainPasswordCheck.Text, (String)txtHashedPasswordCheck.Text));
               Task_VerifyPassword.ContinueWith(t => { throw new BCrypt.Net.SaltParseException(); }, TaskContinuationOptions.OnlyOnFaulted);
                SetCursor(Cursors.WaitCursor);
                isMatch = Task_VerifyPassword.Result;
            }
            catch (BCrypt.Net.SaltParseException e2)
            {
                SetCheckLabel(e2.Message.ToString(), Color.Red, Color.Black);

            }
            if (isMatch)
            {
                SetCheckLabel("Passwords Match", Color.Black, Color.Green);
                SetCursor(Cursors.Default);
            }
            else
            {
                SetCheckLabel("Passwords Don't Match", Color.Red, Color.Black);
                SetCursor(Cursors.Default);
            }
        }
    }

【问题讨论】:

    标签: c# winforms exception-handling task-parallel-library


    【解决方案1】:

    异常未处理,因为它是在一个线程(线程池线程,ContinueWith 运行)中引发的,但您在另一个(GUI 线程)上捕获它。

    我强烈建议使用 .NET 4.5(或带有 Microsoft.Bcl.Async 包的 .NET 4)附带的 async-await 习惯用法的所有好处。有了它,处理从异步方法抛出的异常变得非常自然,并且在捕获的 SynchronisationContext 上执行继续(await 之后的代码)。你可以这样写:

    private async void btncheckPassword_Click(object sender, EventArgs e)
    {
        if(txtPlainPasswordCheck.TextLength > 0 &&   txtHashedPasswordCheck.TextLength > 0)
        {
            bool isMatch = false;
            SetCursor(Cursors.WaitCursor);
    
            try
            {
               isMatch = await Task.Run(
                  () => 
                  {  
                     try
                     {
                        return BCrypt.Net.BCrypt.Verify(
                           (String)txtPlainPasswordCheck.Text,                    
                           (String)txtHashedPasswordCheck.Text)
                        );
                     }
                     catch
                     {
                        throw new BCrypt.Net.SaltParseException(); 
                     }
                  }
               ); 
    
               if (isMatch)
               {
                   SetCheckLabel("Passwords Match", Color.Black, Color.Green);
               }
               else
               {
                  SetCheckLabel("Passwords Don't Match", Color.Red, Color.Black);    
               }
            }
            catch (BCrypt.Net.SaltParseException e2)
            {
                SetCheckLabel(e2.Message.ToString(), Color.Red, Color.Black);
            }
    
            SetCursor(Cursors.Default);
        }
    }
    

    注意:我不熟悉 BCrypt 库,但从 Verify 捕获 any 异常然后抛出 BCrypt.Net.SaltParseException 听起来不是一个好主意(你甚至说这个异常是'被包裹'扔,但你实际上是自己扔的)。最好允许传播任何异常:

    isMatch = await Task.Run(
       () => 
       {  
          return BCrypt.Net.BCrypt.Verify(
             (String)txtPlainPasswordCheck.Text,                    
             (String)txtHashedPasswordCheck.Text)
          );
       }
    ); 
    

    【讨论】:

    • 谢谢,link 的工作就像魔术一样,我只是没有为 catch 语句指定任何参数。
    猜你喜欢
    • 2023-03-30
    • 2013-03-09
    • 1970-01-01
    • 2021-08-27
    • 1970-01-01
    • 2013-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多