【问题标题】:uncatchable exception from unreachable code来自无法访问的代码的无法捕获的异常
【发布时间】:2010-02-18 12:57:13
【问题描述】:

我在我的 C# 2.0 WinForms 应用程序中遇到了一个非常奇怪的问题,我什至不确定它是否值得这样问,因为问题发生在一个奇怪的设置中,我不认为你可以在没有我的情况下重现它来源,但我完全没有想法。

我有一个表单,左边是 TreeView,右边是 ListViewTreeView 显示来自特定文件夹的所有可用文件和子文件夹(其中包含我的应用程序所需的文档)。如果选择了文件夹,ListView 将显示所选文件夹中的所有文件和子文件夹。在启动时,我从文件夹中填充 TreeView,然后通过代码选择第一个 TreeNode(在我的情况下,它是一个文件夹)。之后 TreeView 的内容如下所示:

-folder
   -file1
   -file2

选择文件夹会触发TreeViewAfterSelecedEvent。因为选择了一个文件夹,所以我使用以下方法填充 ListView

private void fillOverview(FAFolder folder)
{
    lv_overview.Items.Clear();
    ListViewItem item;
    foreach (FAFile file in folder.sortedContent)
    {
        if (file is FAFolder)
        {
            item = new ListViewItem(file.Name, "Folder"); //exception got thrown here
        }
        else
        {
            item = new ListViewItem(file.Name, file.Name);
        }
        item.Tag = file;
        lv_overview.Items.Add(item);
    }
}

正如您所见,没有子文件夹,因此在此设置中不应触及 item = new ListViewItem(file.Name, "Folder"); 行,但时不时会抛出 NullReferenceException。如果我用 try/catch 包装这一行,异常就会被抛出到 catch 块中。我尝试检查所有内容是否为null,但没有空引用。或者,如果我在此行之前添加一个MessageBox,仍然会抛出异常并且不会弹出MessageBox。这使我得出结论,execption stacktrace 错误和/或此异常来自其他 Thread 或类似的东西。

我是一个非常乐观的人,我知道 SO 社区有多么聪明,但我认为没有人能指出问题所在。所以我实际上正在寻找的是提示和建议,我如何找到和调试这种奇怪行为的原因。

编辑:

internal abstract class FAFile
{
    internal string Name;
    internal readonly FAFolder Parent;
    internal FAFile(FAFolder parent)
    {
        this.Parent = parent;
    }
}

internal sealed class FAFolder : FAFile
{
    internal readonly IDictionary<string, FAFile> Content = new Dictionary<string, FAFile>();
    internal FAFolder(FAFolder parent, string name) : base(parent)
    {
        this.Name = name;
    }
}

internal sealed class FADocument : FAFile
{
    public readonly string Path;
    public FADocument(FAFolder parent, string path): base(parent)
    {
        this.Path = path;
        this.Name = System.IO.Path.GetFileNameWithoutExtension(path);
    }
}

【问题讨论】:

  • 如果我们能看到FAFolder和FAFile的代码会容易很多
  • 发布堆栈跟踪也很有用
  • 您是否检查过 folder.sortedContent 的结果以确保您获得了预期的结果?
  • 你能显示排序的内容吗?我认为这是一个 ICompareable 或类似的?

标签: c# winforms exception


【解决方案1】:

您是否尝试过对folder.sortedContent 进行空检查?

通常 ReSharper 会提示我类似的东西应该有一个空检查。

如果您想确定,请在代码中的 foreach 循环上方添加以下行:

if (folder.sortedContent == null) throw new Exception("It was null, dangit!");

【讨论】:

    【解决方案2】:

    在你提到的那一行:

    item = new ListViewItem(file.Name, "Folder")
    

    唯一可能导致 NullReferenceException 的情况是file 为 null(除非从 ListViewItem 构造函数本身抛出异常)。

    您没有提供 folder.sortedContent 的代码,所以我无法确定 - 但在某些情况下,此集合中的某个元素是否可能为空?

    如果 ListViewItem 构造函数抛出异常,则需要使用 Reflector 查看代码,或下载参考源。

    【讨论】:

    • file 不能是 null,因为 if (file is FAFolder)null is object 总是 falsesortedContent 总是返回 new List()。但是让我们假设sortedContent == null,而不是foreach 的主体不会被执行。
    【解决方案3】:

    我的一位同事刚刚找到了答案(可能)。我使用一个线程将ImageList 从硬盘加载到ListView,这个线程有时会冻结,如果我分配一个 ImageKey 它会失败。这不能解释为什么异常无法捕获或为什么会在此(无法访问)行中引发异常。但我坚信这是问题的根源。

    【讨论】:

      【解决方案4】:

      那条线不是不可到达的。因为 FAFolder 派生自 FAFile,所以 'file is FAFolder' 可能会返回 true。

      但是,这意味着该文件不为空,除非它正在被另一个线程更改。

      编辑:文件不能被另一个线程更改,因为它是本地引用。你能提供异常的堆栈跟踪吗?这个我现在很感兴趣。

      【讨论】:

        【解决方案5】:

        我不禁想知道 FAFolder 是否包含“。”还是父目录和子目录的“..”?并因此导致排序中断?

        如果事实证明这是不正确的,这个答案将被相应地编辑?

        希望这会有所帮助, 此致, 汤姆。

        【讨论】:

          【解决方案6】:
          • 此异常是否可按需重现?
          • 能否显示异常的堆栈跟踪?
          • 抛出异常时还有哪些线程在运行?

          一般来说,有两种方法可以调试这种类型的东西。第一种方式就是所谓的“科学”调试:

          1. 设计一个理论来解释观察到的行为。
          2. 设计一个实验来检验理论。
          3. 运行实验并观察结果。

          第二种方法是逐段剥离实际代码,直到不再触发异常。那么你就有了进一步调查的重要线索。

          这让我得出结论,execption stacktrace 是错误的......

          假设problem is in your own code 通常更容易开始。

          【讨论】:

            猜你喜欢
            • 2018-08-31
            • 2011-04-19
            • 2019-07-17
            • 2016-05-28
            • 2019-08-02
            • 2011-09-22
            • 2011-12-12
            • 2014-06-23
            • 2013-09-01
            相关资源
            最近更新 更多