【问题标题】:IOException vs checking File.Exists?IOException 与检查 File.Exists?
【发布时间】:2012-08-20 20:21:14
【问题描述】:

(我搜索了类似的主题,但找不到任何解决此特定问题的内容,尽管有几个类似的主题,例如 herehere。)

我正在评估我们的应用程序的性能,我注意到我们收到了一些 IOExceptions“无法找到资源”。我不确定它到底发生了多少次(很大程度上取决于用户如何使用该应用程序),但至少有十几个左右。

我假设异常通常会带来性能开销,就像File.Exists() 这样的文件 I/O 调用也是如此。我知道在尝试加载文件之前检查文件是否存在总是一个好习惯。我的问题是,如果我检查这个特定文件是否存在,我会看到多少性能提升? (同样,忽略“无论如何你都应该这样做”,我只是想了解性能)。

选项 1:

try
{
    return (ResourceDictionary) Application.LoadComponent(uri);
}
catch (Exception)
{
    //If it's not there, don't do anything
}

这不会进行额外的 IO 调用,但有时会抛出并吞下异常。

选项 2

if(File.Exists(uri))
{
    return (ResourceDictionary) Application.LoadComponent(uri);
}

【问题讨论】:

  • 你怎么知道它“总是一个好的做法”?
  • 选项二引入了竞争条件。
  • 选项 2 有竞争条件。任何 IO 操作都可能会失败,即使您之前已经检查过了。
  • 你是对的,它可能并不总是这样,但一般来说你总是想检查文件是否存在。几项大学作业因未检查而被扣分;)
  • 这就是你所说的外生异常。 blogs.msdn.com/b/ericlippert/archive/2008/09/10/…

标签: c# wpf performance file-io exception-handling


【解决方案1】:

一般来说,如果文件应该存在(即:它是应用程序部署的一部分),那么我会使用异常检查,仅此而已。这是因为,在这种情况下,异常确实是一种异常和意外情况。

如果文件是用户输入的,检查是否存在就变得很有意义。但是,这仍然不能消除异常处理的需要,因为文件可以在您检查和打开/使用它的时间之间被删除。因此,您仍然需要异常处理 - 在这种情况下,您可能仍希望只使用您的第一个选项代码,但请确保异常处理足够干净以始终提供行为,即使如果文件不存在。

【讨论】:

  • 我同意你的看法。不幸的是,我认为实现此功能的开发人员没有意识到它在某些情况下可能不存在。正在加载的文件已部署,但仅针对某些程序集部署,但此逻辑存在于基类中,如果有意义的话,可能会在没有该文件的程序集上调用该逻辑。
  • File.Exists 无论如何都会在内部抛出异常,因此最终结果是相同的。
【解决方案2】:

我看不出您的两个选项之间存在很大的性能差异。大部分工作是定位和读取文件,所以在这两种情况下你都必须这样做。如果您不希望用户在应用程序运行时添加/删除此文件,那么缓存结果可能很有用。所以你可能会做类似的事情

private static Dictionary<Uri, ResourceDictionary> _uriToResources =
  new Dictionary<Uri, ResourceDictionary>();
public static ResourceDictionary GetResourceDictionary(Uri uri)
{
  ResourceDictionary resources;
  if (_uriToResources.TryGetValue(uri, out resources))
  {
    return resources;
  }

  try
  {
     resources = (ResourceDictionary)Application.LoadComponent(uri);
  }
  catch
  {
     // could prompt/alert the user here.
     resources = null; // or an appropriate default.
  }

  _uriToResources[uri] = resources;
  return resources;
}

这将防止您重复尝试加载不存在的资源。这里我返回一个空对象,但使用一些默认值作为后备可能会更好。

【讨论】:

    【解决方案3】:

    File.Exists 也会在内部引发异常。所以性能会非常相似。

    这是来自 File.cs 的代码,其中包含 File.Exists 调用的辅助方法。

     [SecurityCritical]
        private static bool InternalExistsHelper(string path, bool checkHost)
        {
          try
          {
            if (path == null || path.Length == 0)
              return false;
            path = Path.GetFullPathInternal(path);
            if (path.Length > 0 && Path.IsDirectorySeparator(path[path.Length - 1]))
              return false;
            FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, path, false, false);
            return File.InternalExists(path);
          }
          catch (ArgumentException ex)
          {
          }
          catch (NotSupportedException ex)
          {
          }
          catch (SecurityException ex)
          {
          }
          catch (IOException ex)
          {
          }
          catch (UnauthorizedAccessException ex)
          {
          }
          return false;
        }
    

    【讨论】:

      猜你喜欢
      • 2013-11-08
      • 2011-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-20
      • 2018-04-20
      • 2013-02-04
      • 2012-05-25
      相关资源
      最近更新 更多