C# 我如何确保一个操作赢得';不要破坏整个应用程序?
我有一个应用程序执行一些额外的工作,如清理旧日志、发送通知等。如果一个作业失败,我不希望整个应用程序停止工作,不执行剩下的作业 那么比如说,C# 我如何确保一个操作赢得';不要破坏整个应用程序?,c#,.net,exception,crash,C#,.net,Exception,Crash,我有一个应用程序执行一些额外的工作,如清理旧日志、发送通知等。如果一个作业失败,我不希望整个应用程序停止工作,不执行剩下的作业 那么比如说, await SendUsersBirthdayEmailsAsync(); // <-- if something fails while trying to send birthday emails here, I don't want the app to stop working and not clean logs and so on...
await SendUsersBirthdayEmailsAsync(); // <-- if something fails while trying to send birthday emails here, I don't want the app to stop working and not clean logs and so on...
await DeleteOutdatedLogsAsync();
await SendSystemNotificationsAsync();
等待SendUsersByrthdayEmailsAsync();// 对可能失败的代码的每个部分使用try catch
块。
根据需要,使用try catch finally
block
在每个catch
块上,根据需要记录异常。我使用Nlog进行日志记录,因此我建议对此进行研究
try{
//do work here
}
catch(Exception e){
//log exception here
}
//optional
finally{
//do optional needed work here
}
大概是这样的:
public bool SendUsersBirthdayEmailsAsync(){
try{
SendMail();
}
catch(Exception e){
LogException(e);
}
//optional
finally{
OptionalWork();
}
}
编辑:关于避免使用泛型异常
您始终可以使用多个catch
块为每种类型的异常定义不同的行为。当您知道可能出现的异常类型时,这非常有用。
例如:
编辑2:用于异常处理
在可能产生异常的代码周围使用try/catch
块,您的代码可以从该异常中恢复。在catch
块中,始终将异常从派生度最高的顺序排列到派生度最低的顺序。所有异常都源自异常
。对于基本异常类,前面有catch
子句的catch
子句不会处理更多派生异常。当代码无法从异常中恢复时,不要捕获该异常。如果可能,启用调用堆栈上的方法以进行恢复
使用
语句或最后使用块清理分配给的资源。更喜欢使用语句在抛出异常时自动清理资源。最后使用块
清理未实现IDisposable的资源
。finally
子句中的代码几乎总是在抛出异常时执行
运行此代码表明,在任务内抛出异常不会停止整个程序 如果您已经在使用调度程序执行此任务,为什么不将其拆分为较小的任务?这样一来,如果一个动作失败,它就不会打倒所有其他动作。此外,拥有许多具有专门职责的小型应用程序是一种很好的做法,而不是一个无所不能的通用应用程序。如果您正在寻找一个可靠的选项来确保流程完成并可跟踪,您可以选择。您还可以通过处理异常来设置重试逻辑,以防失败 由于这些方法的名称表明,这些方法彼此独立,因此只需确保每个方法都返回一个等待的任务,并将它们放入列表中即可。您使用的wait
表明,他们已经这样做了
在它周围放置一个try catch并捕获AggregateExeption
List<Task> tasks = new List<Task>();
try
{
tasks.Add(SendUsersBirthdayEmailsAsync());
tasks.Add(DeleteOutdatedLogsAsync());
tasks.Add(SendSystemNotificationsAsync());
Task.WhenAll(tasks); // waits for all tasks to finish
}
catch (Exception e)
{
//Log e.ToString(); will give you all inner exceptions of the aggregate exception as well, incl. StackTraces, so expect possibly a lot of chars, wherever you log it.
}
List tasks=newlist();
尝试
{
添加(sendUsersBithDayEmailsAsync());
添加(DeleteOutdatedLogsAsync());
添加(SendSystemNotificationsAsync());
Task.WhenAll(tasks);//等待所有任务完成
}
捕获(例外e)
{
//Log e.ToString();还将为您提供聚合异常的所有内部异常,包括StackTraces,因此无论您在何处记录,都可能需要大量字符。
}
这也可能加快速度,因为它们现在是并行运行的。但是,由于它们似乎都在数据库上工作(很可能是相同的),因此,由于调度开销的原因,它们可能不会太多。您可以使用实现您的方法,并让它们返回布尔值。
让每个方法自己处理异常,这样您就可以确保不会抛出未处理的异常来杀死您的应用程序
如果失败将导致无法恢复的程序状态,则方法应返回false,并且应用程序应以干净的方式自行退出。未观察到的任务异常
由于您正在使用TaskScheduler,请签出
在即将触发故障任务的未观察到的异常时发生
异常升级策略,默认情况下,将终止
处理
您需要在每个函数中使用Try-Catch,如下所示
try{
//write your code
}
catch(Exception e){
//your exception will be here
}
public void insertcity()
{
try
{
//Insert city programming
}
catch (exception ex)
{
clsLog.InsertLog(ex.Message,"insertCity");
//do something else you want.
}
}
您可以为该异常生成日志文件。
只需为日志文件做一件事。创建日志类和日志文件生成函数。
在所有函数的catch区域中调用该函数
让您创建一个名为clsLog的日志类。和一个名为InsertLog的静态函数(字符串异常,字符串函数名)
在all函数中使用此日志方法,如下所示
try{
//write your code
}
catch(Exception e){
//your exception will be here
}
public void insertcity()
{
try
{
//Insert city programming
}
catch (exception ex)
{
clsLog.InsertLog(ex.Message,"insertCity");
//do something else you want.
}
}
希望它能有所帮助。所用的-符合我的想法-不过我会再做一件-取消代币-有一个时间限制,你认为多长时间足够-以便一切都完成
等待中的单个任务意味着,当它们分别执行时,它们都会在此时返回到一起。如果发生agreggate异常,您可以捕获它们,然后确定是超时还是需要记录的内容
关于未处理异常和未处理任务异常的两个建议也应该包括在内——无论出于什么原因,它们停止了
我也会考虑将其设置为Windows服务,这样您就可以在启动时将取消令牌传递到任务中,并在服务实际运行时启用计时器,而不是安排任务,然后通过所有异常处理,您可以看到日志随时间的推移告诉您的内容,这比控制台更具弹性应用程序对我来说——但这就是我们通常以这种方式运行任务的方式
您可以在控制台应用程序中启动和停止这样的服务进行测试,然后将其交给一个处理OnStart和OnStop事件的项目。将取消令牌传入OnStop将取消令牌并停止服务循环。我想如果您使用
try{
//your nice work
}
catch(Exception e){
//hmm.. error ok i will show u
}
//optional
finally{
//again start the operation if u failed here.
}
我也提出了同样的申请,其中一些
public void insertcity()
{
try
{
//Insert city programming
}
catch (exception ex)
{
clsLog.InsertLog(ex.Message,"insertCity");
//do something else you want.
}
}
try{
//your nice work
}
catch(Exception e){
//hmm.. error ok i will show u
}
//optional
finally{
//again start the operation if u failed here.
}
MyTask().GetAwaiter().GetResult();
await SendUsersBirthdayEmailsAsync().ConfigureAwait(false);