C# .Net应用程序即使在try catch块C中也会崩溃#

C# .Net应用程序即使在try catch块C中也会崩溃#,c#,C#,我有一个WPF应用程序,它有一堆用户控件、页面等。 当我部署并运行应用程序时,有时它会崩溃并关闭。非常断断续续。我必须转到事件查看器并查看Windows日志以查看发生了什么。我将在日志中找到错误的压缩版本: Application: MyApp.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: Sys

我有一个WPF应用程序,它有一堆用户控件、页面等。 当我部署并运行应用程序时,有时它会崩溃并关闭。非常断断续续。我必须转到事件查看器并查看Windows日志以查看发生了什么。我将在日志中找到错误的压缩版本:

 Application: MyApp.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
  Exception Info: System.InvalidOperationException
   at System.ThrowHelper.ThrowInvalidOperationException(System.ExceptionResource)
   at System.Nullable`1[[System.TimeSpan, mscorlib, Version=4.0.0.0, Culture=neutral, 
  PublicKeyToken=b77a5c561934e089]].get_Value()
  at MyApp.UserControls.UserCountdown+<>c__DisplayClass13_0.<StartAnimation>b__0(
Windows日志错误不显示行号或任何内容。我不是在寻找编码,我想知道如何才能阻止我的应用程序完全崩溃,并实际降落在我的try-catch块而不是事件查看器中

另外,这是我的全部功能。不确定这是否有帮助:

public void StartAnimation()
    {
        try
        {

        double from = -90;
        double to = 270;
        int seconds = Seconds;
        int newSecs = seconds;
        if (Seconds > 60)
            newSecs = newSecs / 2;

        TimeSpan duration = TimeSpan.FromSeconds(Seconds);
        storyboard = new Storyboard();
        DoubleAnimation animation = new DoubleAnimation(from, to, new Duration(duration));

        Storyboard.SetTarget(animation, Arc);
        Storyboard.SetTargetProperty(animation, new PropertyPath("EndAngle"));

        storyboard.CurrentTimeInvalidated += (s, e) =>
        {
            int diff = (int)((s as ClockGroup).CurrentTime.Value.TotalSeconds);
            Seconds = seconds - diff;
            TimeSpan t = new TimeSpan(0, 0, Seconds);
            if (t.Hours > 0)
            {
                timeLabel.FontSize = 16;
                TimeDisplay = $"{t.Hours.ToString("D2")}:{t.Minutes.ToString("D2")}:{t.Seconds.ToString("D2")}";
            }
            else if (t.Minutes > 0)
            {
                timeLabel.FontSize = 25;
                TimeDisplay = $"{t.Minutes.ToString("D2")}:{t.Seconds.ToString("D2")}";
            }
            else
            {
                timeLabel.FontSize = 30;
                TimeDisplay = $"{t.Seconds.ToString("D2")}";
            }
        };

        storyboard.Children.Add(animation);
        storyboard.Begin();
        }
        catch (Exception ex)
        {
            Emailer.SendEmail($"Error calling StartAnimation - {ex.StackTrace}", ex.Message, "", "", "");
        }

    }

您遇到此问题的原因是C#事件处理程序无法安全地抛出异常。有一个很好的答案,可以更详细地解释原因,但要解释一下:

从事件处理程序引发异常会使调用者(触发事件)在确保其他事件处理程序也接收事件的同时,对如何安全地继续操作几乎没有选择

在这种情况下,触发事件的类(
情节提要
)似乎没有捕获事件处理程序引发的异常,而是允许程序崩溃(在某些方面,这是最安全的方法)

回到您的代码,您可以大致简化为以下结构:

试试看
{
var storyboard=新故事板();
故事板。事件+=(o,e)=>{
抛出新异常(“示例”);
};
故事板。开始();
}
捕获(例外)
{
//不要撞车
}
问题是
try-catch
块将只捕获在该try-catch的调用堆栈中执行的代码引发的异常。事件处理程序本身可能正在另一个线程的调用堆栈上执行(在本例中,很可能是
ThreadPool
中的线程),并且不在此try-catch块内。这意味着,除非
情节提要
类从事件处理程序捕获异常,然后在其
Begin()
方法的范围内重新抛出它们(它没有这样做),否则您将遇到未处理的异常

要解决此问题,只需将事件处理程序中的代码包装在自己的try-catch块中,如下所示:

storyboard.CurrentTimeInvalidated+=(s,e)=>
{
尝试
{
//TODO:在此处添加事件处理程序代码
}
捕获(例外情况除外)
{
//TODO:在此处处理动画中触发的异常
}
};

在调试过程中,在电离发生之前的最后一行是什么?也许是红鲱鱼,请检查您的“秒”和“秒”-TimeSpan duration=TimeSpan.FromSeconds(秒)???我假设两个代码摘录中的
Exception
都是指
System.Exception
而不是其他类型?我知道通常情况是这样的,但由于它们似乎没有捕获所有(通常可捕获的)异常,可能它们实际上捕获了其他异常?问题可能是
int diff=(int)((s作为时钟组).CurrentTime.Value.TotalSeconds)
CurrentTime
可能是
null
public void StartAnimation()
    {
        try
        {

        double from = -90;
        double to = 270;
        int seconds = Seconds;
        int newSecs = seconds;
        if (Seconds > 60)
            newSecs = newSecs / 2;

        TimeSpan duration = TimeSpan.FromSeconds(Seconds);
        storyboard = new Storyboard();
        DoubleAnimation animation = new DoubleAnimation(from, to, new Duration(duration));

        Storyboard.SetTarget(animation, Arc);
        Storyboard.SetTargetProperty(animation, new PropertyPath("EndAngle"));

        storyboard.CurrentTimeInvalidated += (s, e) =>
        {
            int diff = (int)((s as ClockGroup).CurrentTime.Value.TotalSeconds);
            Seconds = seconds - diff;
            TimeSpan t = new TimeSpan(0, 0, Seconds);
            if (t.Hours > 0)
            {
                timeLabel.FontSize = 16;
                TimeDisplay = $"{t.Hours.ToString("D2")}:{t.Minutes.ToString("D2")}:{t.Seconds.ToString("D2")}";
            }
            else if (t.Minutes > 0)
            {
                timeLabel.FontSize = 25;
                TimeDisplay = $"{t.Minutes.ToString("D2")}:{t.Seconds.ToString("D2")}";
            }
            else
            {
                timeLabel.FontSize = 30;
                TimeDisplay = $"{t.Seconds.ToString("D2")}";
            }
        };

        storyboard.Children.Add(animation);
        storyboard.Begin();
        }
        catch (Exception ex)
        {
            Emailer.SendEmail($"Error calling StartAnimation - {ex.StackTrace}", ex.Message, "", "", "");
        }

    }