5

(비슷한 스레드를 검색해 보았지만이 특정 문제를 해결 한 항목을 찾을 수 없었습니다.이리이리.)

우리 앱의 성능을 평가 중이고 일부 IO 예외가 "리소스를 찾을 수 없습니다"라는 메시지가 나타납니다. 정확히 얼마나 많은 시간이 일어 났는지는 잘 모르겠지만 (대부분 사용자가 앱을 사용하는 방식에 달려있다.), 적어도 12 개 정도는된다.

나는 일반적으로 파일 I / O 호출처럼 성능이 비싸다고 가정합니다.File.Exists(). 파일을로드하고로드하기 전에 파일이 있는지 항상 확인하는 것이 좋습니다. 내 질문은, 특정 파일이 존재하는지 확인하면 얼마나 많은 성능 향상을 볼 수 있습니까? (다시 말하지만, "어쨌든이 일을해야합니다."나는 단지 성능에 대한 이해를 얻으려고 노력하고 있음).

옵션 1:

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

이것은 여분의 IO 호출을하지 않지만 때로는 throw하고 삼키는 예외를 만듭니다.

옵션 2:

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


  • 당신이 " 항상 좋은 연습 "이라는 것을 어떻게 알 수 있습니까? - Gabe
  • 두 번째 옵션은 경합 조건을 도입합니다. - asawyer
  • 옵션 2에는 경쟁 조건이 있습니다. 이전에 IO 작업을 확인한 경우에도 IO 작업이 실패 할 수 있습니다. - Mike Zboray
  • 항상 그렇다고 볼 수는 없지만 일반적으로 파일이 있는지 항상 확인하고 싶습니다. 몇 가지 대학 과제는 확인하지 않은 점을 도킹 한 것입니다. - Devin
  • 그것은 당신이 외생적 인 예외라고 부를 것입니다.blogs.msdn.com/b/ericlippert/archive/2008/09/10/… - asawyer

3 답변


6

일반적으로 파일할까요존재 (예 : 응용 프로그램 배포의 일부), 그렇다면 예외 검사 만 사용하면됩니다. 이 경우 예외는 실제로 예외적이고 예기치 않은 상황이기 때문입니다.

파일이 사용자가 입력 한 것 인 경우, 존재 여부를 확인하는 것이 잠재적 인 의미가 있습니다. 그러나이 경우에도 예외 처리가 필요하지 않습니다.할 수 있었다확인한 시간과 열어 본 시간 사이에 삭제 될 수 있습니다. 따라서 예외 처리가 여전히 필요합니다.이 경우 예외 처리가 필요합니다.할 수있다여전히 첫 번째 옵션 코드를 사용하고 싶지만 예외 처리가 파일이 존재하지 않더라도 항상 동작을 제공 할만큼 깨끗한 지 확인하십시오.


  • 나는 너에게 동의한다. 불행하게도 나는 이것을 구현 한 개발자가 어떤 상황에서는 존재하지 않는다는 것을 깨닫지 못했다고 생각한다. 로드되는 파일은 배포되었지만 특정 어셈블리에만 배포되지만이 논리는 기본 클래스에 있으므로 어셈블리에 대해 호출 될 수도 있습니다. - Devin
  • File.Exists는 내부적으로 예외를 throw하므로 결과는 같습니다. - rolls

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

이렇게하면 존재하지 않는 리소스를 반복적으로로드하지 못하게됩니다. 여기에 null 객체가 반환되지만 일부 기본값을 대체로 사용하는 것이 좋습니다.


1

File.Exists는 내부적으로 예외도 throw합니다. 따라서 성능은 매우 유사합니다.

다음은 File.Exists가 호출하는 도우미 메서드가 포함 된 File.cs의 코드입니다.

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

연결된 질문


관련된 질문

최근 질문