5

(我搜索了类似的线程,但找不到任何解决这个特定问题的东西,尽管有几个类似的,比如这里这里。)

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

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

选项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);
}
4

3 回答 3

6

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

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

于 2012-08-20T20:26:23.027 回答
1

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

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;
}

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

于 2012-08-20T20:46:03.517 回答
1

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;
    }
于 2017-12-04T02:35:27.383 回答