在什么情况下会捕获所有(catch(Exception ex))并不真正捕获所有?

时间:2011-11-14 05:14:55

标签: c# .net exception windows-phone-7

我的崩溃报告系统告诉我异常到达Unhandled Exception处理程序,并查看发起这个的代码,我看不出这是怎么回事。代码完全同步并包装在try /捉。

澄清:此代码在Windows Phone 7上运行,并且在不受控制的环境(即用户设备)上的生产中发生异常。

以下是代码:

private void LoadUserData()   
{   
    try  
    {   
        UserData = UserData.Deserialize(UserDataFileName, true);   

        // We succeeded. Backup the file, if possible.   
        if (IsoFile.Store.FileExists(UserDataFileName))   
        {   
             try  
             {   
                 IsoFile.CopyFile(UserDataFileName, UserDataFileBackupName);   
             }   
             catch (Exception ex)   
             {   
                 EventManager.Current.ShipAssert("LoadUserData.Backup", ex);   
             }   
         }   
     }   
     catch (Exception ex)   
     {   
         string currentFile = "";   
         try  
         {   
             currentFile = IsoFile.ReadAllLines(UserDataFileName);   
         }   
         catch (Exception exInner)   
         {   
             currentFile = "Exception when trying to read file: " + exInner.ToString();   
         }   
    }   
}  

到达未处理的异常处理程序的异常:

System.InvalidOperationException: There is an error in XML document (129, 54). ---> System.InvalidOperationException: There is an error in XML document (129, 54). ---> System.Xml.XmlException: Unexpected end of file has occurred. The following elements are not closed: value, item, VotedUrls, UserData. Line 129, position 54.    at    
System.Xml.XmlTextReaderImpl.Throw(Exception e)    at    
System.Xml.XmlTextReaderImpl.Throw(Int32 res, String resString, String arg)    at    
System.Xml.XmlTextReaderImpl.Throw(Int32 pos, Int32 res, String resString, String arg)    at    
System.Xml.XmlTextReaderImpl.ThrowUnclosedElements()    at    
System.Xml.XmlTextReaderImpl.ParseElementContent()    at    
System.Xml.XmlTextReaderImpl.Read()    at    
System.Xml.XmlTextReader.Read()    at    
System.Xml.XmlReader.ReadEndElement()    at    
System.Xml.Serialization.XmlSerializationReader.DeserializePrimitiveElement(LogicalType deserializeAs, Accessor accessor, Fixup fixup, Object fixupTarget, String identifier, Boolean emptyValue, Boolean nullValue)    at    
System.Xml.Serialization.XmlSerializationReader.deserializeElement(Accessor accessor, Fixup fixup, Object fixupTarget)    at    
System.Xml.Serialization.XmlSerializationReader.DeserializeElement(Accessor accessor, Fixup fixup)    at    
System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)    at    
SocialEbola.Shared.Utils.SerializableDictionary`2.ReadXml(XmlReader reader)    at    
System.Xml.Serialization.XmlSerializationReader.DeserializeSerializableElement(LogicalType deserializeAs, Accessor accessor, Fixup fixup, Object fixupTarget, String identifier, Boolean emptyValue, Boolean nullValue)    at    
System.Xml.Serialization.XmlSerializationReader.deserializeElement(Accessor accessor, Fixup fixup, Object fixupTarget)    at    
System.Xml.Serialization.XmlSerializationReader.DeserializeElementMember(MemberValueCollection members, Object fixupTarget, Hashtable internalState, Boolean& firstElement)    at    
System.Xml.Serialization.XmlSerializationReader.deserializeMembers(MemberValueCollection members, Object fixupTarget)    at    
System.Xml.Serialization.XmlSerializationReader.DeserializeComplexElement(LogicalType deserializeAs, Accessor accessor, Fixup fixup, Object fixupTarget, String identifier, Boolean emptyValue, Boolean nullValue)    at    
System.Xml.Serialization.XmlSerializationReader.deserializeElement(Accessor accessor, Fixup fixup, Object fixupTarget)    at    
System.Xml.Serialization.XmlSerializationReader.DeserializeElement(Accessor accessor, Fixup fixup)    at    
System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)    at    
System.Xml.Serialization.XmlSerializer.Deserialize(Stream stream)    at    
SocialEbola.Lib.Serialization.SerializeHelper`1.Deserialize(Stream stream)    at    
SocialEbola.Lib.Serialization.SerializeHelper`1.Deserialize(String file, Boolean createNew)    at    
Fails.App.LoadUserData()    at    
Fails.App.Application_Launching(Object sender, LaunchingEventArgs e)    at    
Microsoft.Phone.Shell.PhoneApplicationService.FireLaunching()    at    
Microsoft.Phone.Execution.NativeEmInterop.FireOnLaunching()     at    
System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)    at    
SocialEbola.Shared.Utils.SerializableDictionary`2.ReadXml(XmlReader reader)    at    
System.Xml.Serialization.XmlSerializationReader.DeserializeSerializableElement(LogicalType deserializeAs, Accessor accessor, Fixup fixup, Object fixupTarget, String identifier, Boolean emptyValue, Boolean nullValue)    at    
System.Xml.Serialization.XmlSerializationReader.deserializeElement(Accessor accessor, Fixup fixup, Object fixupTarget)    at    
System.Xml.Serialization.XmlSerializationReader.DeserializeElementMember(MemberValueCollection members, Object fixupTarget, Hashtable internalState, Boolean& firstElement)    at    
System.Xml.Serialization.XmlSerializationReader.deserializeMembers(MemberValueCollection members, Object fixupTarget)    at    
System.Xml.Serialization.XmlSerializationReader.D   

这是UserData.Deserialize的代码(来自模板化的基类):

public static T Deserialize(string file, bool createNew)
{
    IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();
    T result;

    if (!store.FileExists(file))
    {
        if (createNew)
        {
            result = new T();
        }
        else
        {
            result = default(T);
        }
    }
    else
    {
        using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(file, FileMode.Open, store))
        {
            result = Deserialize(stream);
        }
    }

    return result;
}

public static T Deserialize(Stream stream)
{
    T t = (T)Serializer.Deserialize(stream);
    return t;
}

Serializer在基类中定义为:

public static XmlSerializer Serializer = new XmlSerializer(typeof(T));

3 个答案:

答案 0 :(得分:1)

更新:我首先要做的是清理您的项目并重建。您可能没有运行您认为正在运行的代码。 (即该堆栈没有行号,可能不是您最近编译的程序集)

现在如果没有解决问题,请继续阅读

在UnhandledException方法处理程序上放置一个断点,并确定调用线程是否与抛出异常的线程相同:

private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    //add this line and put a breakpoint here.
    var threadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
    Log.Error("CurrentDomain_UnhandledException", e.ExceptionObject as Exception);
}

如果两个threadId不同,则可以解释您看到的行为。 (正如@Erno所说)

如果它们是相同的,那么作为测试,我会在您调用Deserialize之前在代码中抛出一个显式的Exception,看看是否被捕获。例如:

throw new Exception("test");
UserData = UserData.Deserialize(UserDataFileName, true); 

然后报告回来。

答案 1 :(得分:1)

在.Net 2.0中,StackOverflowException无法捕获。这可能很容易被您的代码绊倒。唯一的其他无法捕获的异常是.Net 4.0中的AccessViolationException。只有在尝试读取受保护的内存时才会出现这种情况。

我想说StackOverflowException是你最可能的嫌疑人。检查代码中是否有未加盖的递归函数,并尝试单步执行调试器以查看导致它的条件。

答案 2 :(得分:0)

我建议学习并应用一些激励处理最佳实践。

不要使用流量控制的异常(正如您所做的那样),使用它们来报告和处理错误情况。

Catch块应该从错误条件中部分或完全恢复,并可能重新抛出异常或抛出一个新的(可能更具体的异常)。不要将业务逻辑放在catch块中(正如您所做的那样)。这样做可能会有另外一个异常掩码。

仅捕获您将要(至少部分)恢复的异常,或者为了抛出更具体的异常。由于异常是按类型捕获的,这意味着您实际上应该永远不会捕获System.Exception:它太过于通用而无法从中恢复。

出于同样的原因,不要抛出过于笼统的异常,例如System.Exception。研究.Net Framework类库中已定义的异常,或创建直接或间接从System.Exception派生的特定异常类型。

由于按顺序计算给定try块的catch块,因此请确保在catch块之前为更少派生的exceptoin类型放置catch块以获取更多派生异常类型。

任何好的C#编程参考都应提供有关正确使用的指导以及抛出和捕获异常的最佳实践。

考虑到这一点:   - 第14行捕获了哪些异常类型?明确说明。   - 第16行中的代码是否可能抛出异常?如果是这样,会发生什么异常处理?   - 为什么在第22行声明的变量作用于catch块?在第29行分配给它的价值是什么,因为它在那之后就超出了范围?

在您的代码中对这些内容进行排序,然后使用调试器逐步完成它,我相信您已经立即发现了罪魁祸首。