代码之家  ›  专栏  ›  技术社区  ›  Gabriel Bernardone

即使在发生异常后,任务也会持续执行

  •  -2
  • Gabriel Bernardone  · 技术社区  · 6 年前

    方法 相对静力学。Abridatatual公司 在下面的任务中,返回的异常已在方法本身中处理,问题是任务继续执行下一行 var links=ListArquivos。ListalinkDownlaod(驱动程序); 这取决于方法 Abridatatual() 要执行,它还抛出一个异常。我曾尝试在方法中进行处理,将任务放入Try/catch中,但没有任何效果,方法中总是存在异常 ListalinkDownlaod 甚至不应该去那里。

    如何停止任务的执行,例如当我们发送CancellationToken时,但这次是在发生异常时。

    private async Task<List<IWebElement>> Acessar(IWebDriver driver, string data, CancellationToken ct)
    {
        return await Task.Run(() =>
        {
            ct.ThrowIfCancellationRequested();
    
            LoginNgin.Login(config.User, config.Password, driver);
    
            RelatoriosEstaticos.AbrirRelatoriosEstaticos(driver);
    
            RelatoriosEstaticos.AbrirDataAtual(driver, data);
    
            var links = ListArquivos.ListaLinksDownlaod(driver);
    
            MethodInvoker action = delegate { pgbStatus.Maximum = links.Count(); };
            pgbStatus.BeginInvoke(action);
    
            return links;
        });
    }
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Ňuf    6 年前

    如果没有看到 AbrirDataAtual ,但这个方法显然是在处理不应该在那里处理的异常。

    通常,方法应该处理异常 只有 如果它能处理的话 正确地 (由 正确地 我的意思是,它可以将应用程序恢复到程序可以安全继续的状态,通知用户错误等),否则它根本不应该处理它,让异常传播到方法的调用方。

    根据您的问题描述, Abridatatual公司 不(也不能)处理异常 正确地 ,因此您不应该在那里捕获异常(或者如果必须在那里捕获异常,您应该 re-throw it)。以下所有方法(包括 ListArquivos.ListaLinksDownlaod )将一直跳过到处理异常的点。问题解决了!

    以下示例显示如何直接在任务中处理异常(在中删除异常处理后 Abridatatual公司 )。但它可能仍然不是此类异常处理程序的最佳位置,但再次强调,找到这样的位置需要完整的源代码,因此请将其作为一个示例来澄清我所说的内容:

    private async Task<List<IWebElement>> Acessar(IWebDriver driver, string data, CancellationToken ct)
    {
        return await Task.Run(() =>
        {
            ct.ThrowIfCancellationRequested();
    
            LoginNgin.Login(config.User, config.Password, driver);
    
            RelatoriosEstaticos.AbrirRelatoriosEstaticos(driver);
    
            try
            {
                RelatoriosEstaticos.AbrirDataAtual(driver, data);
    
                var links = ListArquivos.ListaLinksDownlaod(driver);
    
                MethodInvoker action = delegate { pgbStatus.Maximum = links.Count(); };
                pgbStatus.BeginInvoke(action);
    
                return links;
            }
            catch (Exception)//Use more specific exception type if possible
            {
                //Do all neccesary to properly handle the exception
            }
        });
    }
    

    如果你仍然相信 Abridatatual公司 方法是处理异常的正确位置,另一种方法是修改 Abridatatual公司 返回指示其操作成功/失败的布尔标志,例如:

    bool AbrirDataAtual(IWebDriver driver, string data)
    {
        try
        {
            //Do all the neccessary stuff
            ...
    
            //Indicate that AbrirDataAtual succeeded
            return true;
        }
        catch(Exception)
        {
            //Handle exception properly
            ...
    
            //Indicate that AbrirDataAtual failed
            return false;
        }
    }
    
    private async Task<List<IWebElement>> Acessar(IWebDriver driver, string data, CancellationToken ct)
    {
        return await Task.Run(() =>
        {
            ct.ThrowIfCancellationRequested();
    
            LoginNgin.Login(config.User, config.Password, driver);
    
            RelatoriosEstaticos.AbrirRelatoriosEstaticos(driver);
    
            if (RelatoriosEstaticos.AbrirDataAtual(driver, data))
            {
                //Continue execution
                var links = ListArquivos.ListaLinksDownlaod(driver);
    
                MethodInvoker action = delegate { pgbStatus.Maximum = links.Count(); };
                pgbStatus.BeginInvoke(action);
    
                return links;
            }
            else
            {
                //AbrirDataAtual failed
                return null;
                //or throw exception if appropriate
                throw new Exception();
            }
        });
    }