为了账号安全,请及时绑定邮箱和手机立即绑定

如何确保操作不会使整个应用程序崩溃?

如何确保操作不会使整个应用程序崩溃?

C#
缥缈止盈 2023-09-16 15:01:56
我有一个应用程序执行一些额外的工作,例如清理旧日志、发送通知等。如果一项作业失败,我不希望整个应用程序停止工作并且不执行剩下的作业。例如,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();你会推荐我搭配什么?
查看完整描述

6 回答

?
慕哥6287543

TA贡献1831条经验 获得超10个赞

try-catch对可能失败的代码的每个部分使用块。

根据您的需要,使用try-catch-finally块。


在每个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块来为每种类型的异常定义不同的行为。当您知道可能会出现什么样的异常时,这非常有用。

例子:


public bool SendUsersBirthdayEmailsAsync(){

    try{

        SendMail();

    }

    catch (ThreadAbortException tae)

    {

        LogException(tae);

        //do something specific

    }

    catch (ThreadInterruptedException tie)

    {

        LogException(tie);

        //do something specific

    }

    catch(Exception e){

        LogException(e);

    }

    //optional

    finally{

        OptionalWork();

    }       

}

编辑 2:异常处理的Microsoft 官方指南。

try/catch在可能生成异常的代码周围使用块,您的代码可以从该异常中恢复。在catch块中,始终将异常从派生最多的到派生最少的排序。所有异常均源自Exception. 更多派生异常不会由catch前面有catch基本异常类子句的子句处理。当您的代码无法从异常中恢复时,不要捕获该异常。如果可能的话,启用调用堆栈上方的方法进行恢复。

清理用using语句或finally块分配的资源。Preferusing语句在抛出异常时自动清理资源。使用finally块来清理未实现的资源IDisposablefinally即使抛出异常,子句中的代码也几乎总是会执行。


查看完整回答
反对 回复 2023-09-16
?
MMTTMM

TA贡献1869条经验 获得超4个赞

您需要在每个函数中使用 Try-Catch,如下所示。


try{

    //write your code

}

catch(Exception e){

    //your exception will be here

}

您可以为该异常生成一个日志文件。只需为您的日志文件做一件事。创建日志类和日志文件生成函数。在所有函数的 catch 区域中调用该函数。


让您创建一个名为clsLog的 Log 类。和一个名为InsertLog(string exception, string functionname)的静态函数。


在您的所有函数中使用此日志方法,如下所示。


public void insertcity()

{

 try

 {

   //Insert city programming

 }

 catch (exception ex)

 {

   clsLog.InsertLog(ex.Message,"insertCity");

   //do something else you want.

 }        

}

希望它会有所帮助。


查看完整回答
反对 回复 2023-09-16
?
不负相思意

TA贡献1777条经验 获得超10个赞

未观察到的任务异常

await SendUsersBirthdayEmailsAsync(); // uses TaskScheduler

由于您正在使用 TaskScheduler,请查看TaskScheduler.UnobservedTaskException。

当故障任务的未观察到的异常即将触发异常升级策略时发生,默认情况下,该策略将终止进程


查看完整回答
反对 回复 2023-09-16
?
青春有我

TA贡献1784条经验 获得超8个赞

正如这些方法的名称所示,这些方法是相互独立的,只需确保每个方法返回一个可等待的任务并将它们放入一个列表中即可。您使用的await建议,他们已经这样做了。


在它周围放置一个 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.

}

这也可能会加快速度,因为它们现在是并行运行的。但由于它们似乎都在数据库上工作(很可能相同),因此由于调度开销,即使有的话,也可能不会太多。


查看完整回答
反对 回复 2023-09-16
?
天涯尽头无女友

TA贡献1831条经验 获得超9个赞

我建议找出您从什么异常中async实际获得此异常并了解您可以在 main 上使用它Thread

MyTask().GetAwaiter().GetResult();

这将允许您查看线程上实际异常的文本await


如果您不希望主线程返回到await您也可以使用的行:

await SendUsersBirthdayEmailsAsync().ConfigureAwait(false);

这只会在最近的空闲线程上继续您的任务。

但需要说的是,这在Android上会导致异常,因为它对使用线程有一些限制。


如果您不想浪费时间或不需要手动处理异常并修复它trycatch finally始终是一个选择。


查看完整回答
反对 回复 2023-09-16
?
眼眸繁星

TA贡献1873条经验 获得超9个赞

Task<Task> task = (SendUsersBirthdayEmailsAsync()

            .ContinueWith(x => Task.WhenAll(DeleteOutdatedLogsAsync(), SendSystemNotificationsAsync())));

await await task;

对于更一般的示例,提供了以下代码:


class TaskTest

{

    public async void Start()

    {


        await (

            (await One().ContinueWith(x => Task.WhenAll(Two(), Three())))

            .ContinueWith(x=> Four()));

    }


    private async Task One()

    {

        await Task.Delay(5000);

        Console.WriteLine("1");

        throw new Exception();

    }


    private async Task Two()

    {

        await Task.Delay(2000);

        Console.WriteLine("2");

        throw new Exception();


    }

    private async Task Three()

    {

        await Task.Delay(3000);

        Console.WriteLine("3");

        throw new Exception();

    }


    private async Task Four()

    {

        await Task.Delay(1000);

        Console.WriteLine("4");

        throw new Exception();

    }

}

运行此代码表明,在任务内引发异常不会停止整个程序。


查看完整回答
反对 回复 2023-09-16
  • 6 回答
  • 0 关注
  • 137 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信