即使发生异常,任务仍会继续执行
Task continuous execution even after exception
下面任务中的方法 RelatoriosEstaticos.AbrirDataAtual 正在返回方法本身已处理的异常,问题是任务继续执行下一个var links = ListArquivos.ListaLinksDownlaod(driver); 这取决于要执行的方法 AbrirDataAtual(),它也会抛出异常.我试图在方法内处理,将任务放在 Try / catch 中,但没有任何效果,方法 ListaLinksDownlaod 中总是存在异常,甚至不应该到达那里。
如何停止任务的执行,比如我们发送了一个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;
});
}
如果没有看到 AbrirDataAtual
的实际实现,就无法确定,但看起来这个方法确实正在处理不应该在那里处理的异常。
一般来说,方法应该只处理异常适当(通过适当 我的意思是它可以将应用程序恢复到程序可以安全继续的状态,通知用户有关错误等),否则它根本不应该处理它并让异常传播到方法的调用者。
根据您对问题的描述,AbrirDataAtual
没有(也不能)正确处理异常,因此您不应该在那里捕获异常(或者如果必须在那里捕获异常,你应该 re-throw 它)。将跳过以下所有方法(包括 ListArquivos.ListaLinksDownlaod
),直到处理异常为止。问题已解决!
下面的例子展示了如何直接在任务中处理异常(在AbrirDataAtual
中移除异常处理之后)。但它可能仍然不是此类异常处理程序的最佳位置,但同样,找到这样的位置需要完整的源代码,因此仅以它为例来阐明我在说什么:
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
}
});
}
如果您仍然认为 AbrirDataAtual
方法是处理异常的正确位置,另一种方法是将 AbrirDataAtual
修改为 return 布尔标志,指示 success/failure它的操作,例如:
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();
}
});
}
下面任务中的方法 RelatoriosEstaticos.AbrirDataAtual 正在返回方法本身已处理的异常,问题是任务继续执行下一个var links = ListArquivos.ListaLinksDownlaod(driver); 这取决于要执行的方法 AbrirDataAtual(),它也会抛出异常.我试图在方法内处理,将任务放在 Try / catch 中,但没有任何效果,方法 ListaLinksDownlaod 中总是存在异常,甚至不应该到达那里。
如何停止任务的执行,比如我们发送了一个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;
});
}
如果没有看到 AbrirDataAtual
的实际实现,就无法确定,但看起来这个方法确实正在处理不应该在那里处理的异常。
一般来说,方法应该只处理异常适当(通过适当 我的意思是它可以将应用程序恢复到程序可以安全继续的状态,通知用户有关错误等),否则它根本不应该处理它并让异常传播到方法的调用者。
根据您对问题的描述,AbrirDataAtual
没有(也不能)正确处理异常,因此您不应该在那里捕获异常(或者如果必须在那里捕获异常,你应该 re-throw 它)。将跳过以下所有方法(包括 ListArquivos.ListaLinksDownlaod
),直到处理异常为止。问题已解决!
下面的例子展示了如何直接在任务中处理异常(在AbrirDataAtual
中移除异常处理之后)。但它可能仍然不是此类异常处理程序的最佳位置,但同样,找到这样的位置需要完整的源代码,因此仅以它为例来阐明我在说什么:
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
}
});
}
如果您仍然认为 AbrirDataAtual
方法是处理异常的正确位置,另一种方法是将 AbrirDataAtual
修改为 return 布尔标志,指示 success/failure它的操作,例如:
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();
}
});
}