다음은 파일 작업 자체와는 별개로이를 수행하는 일반 코드입니다. 다음은 사용 방법에 대한 예입니다.
WrapSharingViolations(() => File.Delete(myFile));
또는
WrapSharingViolations(() => File.Copy(mySourceFile, myDestFile));
재시도 횟수와 재시도 사이의 대기 시간을 정의 할 수도 있습니다.
참고 : 불행히도 기본 Win32 오류 (ERROR_SHARING_VIOLATION)는 .NET에서 노출되지 않으므로 IsSharingViolation
이를 확인하기 위해 반사 메커니즘을 기반으로 하는 작은 해킹 기능 ( )을 추가했습니다 .
/// <summary>
/// Wraps sharing violations that could occur on a file IO operation.
/// </summary>
/// <param name="action">The action to execute. May not be null.</param>
public static void WrapSharingViolations(WrapSharingViolationsCallback action)
{
WrapSharingViolations(action, null, 10, 100);
}
/// <summary>
/// Wraps sharing violations that could occur on a file IO operation.
/// </summary>
/// <param name="action">The action to execute. May not be null.</param>
/// <param name="exceptionsCallback">The exceptions callback. May be null.</param>
/// <param name="retryCount">The retry count.</param>
/// <param name="waitTime">The wait time in milliseconds.</param>
public static void WrapSharingViolations(WrapSharingViolationsCallback action, WrapSharingViolationsExceptionsCallback exceptionsCallback, int retryCount, int waitTime)
{
if (action == null)
throw new ArgumentNullException("action");
for (int i = 0; i < retryCount; i++)
{
try
{
action();
return;
}
catch (IOException ioe)
{
if ((IsSharingViolation(ioe)) && (i < (retryCount - 1)))
{
bool wait = true;
if (exceptionsCallback != null)
{
wait = exceptionsCallback(ioe, i, retryCount, waitTime);
}
if (wait)
{
System.Threading.Thread.Sleep(waitTime);
}
}
else
{
throw;
}
}
}
}
/// <summary>
/// Defines a sharing violation wrapper delegate.
/// </summary>
public delegate void WrapSharingViolationsCallback();
/// <summary>
/// Defines a sharing violation wrapper delegate for handling exception.
/// </summary>
public delegate bool WrapSharingViolationsExceptionsCallback(IOException ioe, int retry, int retryCount, int waitTime);
/// <summary>
/// Determines whether the specified exception is a sharing violation exception.
/// </summary>
/// <param name="exception">The exception. May not be null.</param>
/// <returns>
/// <c>true</c> if the specified exception is a sharing violation exception; otherwise, <c>false</c>.
/// </returns>
public static bool IsSharingViolation(IOException exception)
{
if (exception == null)
throw new ArgumentNullException("exception");
int hr = GetHResult(exception, 0);
return (hr == -2147024864); // 0x80070020 ERROR_SHARING_VIOLATION
}
/// <summary>
/// Gets the HRESULT of the specified exception.
/// </summary>
/// <param name="exception">The exception to test. May not be null.</param>
/// <param name="defaultValue">The default value in case of an error.</param>
/// <returns>The HRESULT value.</returns>
public static int GetHResult(IOException exception, int defaultValue)
{
if (exception == null)
throw new ArgumentNullException("exception");
try
{
const string name = "HResult";
PropertyInfo pi = exception.GetType().GetProperty(name, BindingFlags.NonPublic | BindingFlags.Instance); // CLR2
if (pi == null)
{
pi = exception.GetType().GetProperty(name, BindingFlags.Public | BindingFlags.Instance); // CLR4
}
if (pi != null)
return (int)pi.GetValue(exception, null);
}
catch
{
}
return defaultValue;
}