6

時々失敗するように見えるNetApp NASファイラーがあります。これがネットワークの問題、重い負荷、またはファイラー自体に依存するかどうかはわかりません。問題は、通常のSystem.IO.File.Copy(...)コマンドが1分前に機能し、1分後に再び機能するときに予期せず失敗することがあることです...ファイラーはCIFSファイルシステムで機能しています。

Log4Net ログファイルに例外が表示されます。

System.IO.IOException: 指定されたネットワーク名は使用できなくなりました。System.IO.__Error.WinIOError (Int32 errorCode、String MaybeFullPath) で ...

ネットワーク チームは何が起こったのか、その理由が不明です。ファイルをコピーし、失敗した場合にコピーを再試行する単純な試行/再試行システムを実装できるかどうかを考えています。おそらく、System.IO.File.Copy がCIFS ストレージ用に設計されていますが、通常の NTFS ドライブまたは安定したネットワーク ストレージ用に設計されています。

このコピーと再試行を実行するのに適した一般的なパターンまたは .NET クラスはありますか?それとも、単に次の疑似コードのようなアプローチを使用する必要がありますか?

while(!copied && count <5)
{
  count++;

  try
  {
    //here copy the file
    ...

    //if no exception copy was ok
    copied = true;
  }
  catch
  {
    if(count >= 5)
    {
      // Log that retry limit has been reached...
    }
    else
    {
      // make thread to wait for some time,
      // waiting time can be in function of count or fixed...
    }
  }
} 
4

2 に答える 2

2

私にも同じことが起こります。古いNAS サーバーを使用していますが、時々、ドライブにアクセスできないというエラーが Windows に表示されます。ファイル コピー プロセス
を管理するには、次のサンプルに示すように、代わりに( Windows APIから) CopyFileExを使用できます。

public class SecureFileCopy
{
    public static void CopyFile(FileInfo source, FileInfo destination, 
        CopyFileOptions options, CopyFileCallback callback, object state)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (destination == null) 
            throw new ArgumentNullException("destination");
        if ((options & ~CopyFileOptions.All) != 0) 
            throw new ArgumentOutOfRangeException("options");

        new FileIOPermission(
            FileIOPermissionAccess.Read, source.FullName).Demand();
        new FileIOPermission(
            FileIOPermissionAccess.Write, destination.FullName).Demand();

        CopyProgressRoutine cpr = callback == null ? 
            null : new CopyProgressRoutine(new CopyProgressData(
                source, destination, callback, state).CallbackHandler);

        bool cancel = false;
        if (!CopyFileEx(source.FullName, destination.FullName, cpr, 
            IntPtr.Zero, ref cancel, (int)options))
        {
            throw new IOException(new Win32Exception().Message);
        }
    }

    private class CopyProgressData
    {
        private FileInfo _source = null;
        private FileInfo _destination = null;
        private CopyFileCallback _callback = null;
        private object _state = null;

        public CopyProgressData(FileInfo source, FileInfo destination, 
            CopyFileCallback callback, object state)
        {
            _source = source; 
            _destination = destination;
            _callback = callback;
            _state = state;
        }

        public int CallbackHandler(
            long totalFileSize, long totalBytesTransferred, 
            long streamSize, long streamBytesTransferred, 
            int streamNumber, int callbackReason,
            IntPtr sourceFile, IntPtr destinationFile, IntPtr data)
        {
            return (int)_callback(_source, _destination, _state, 
                totalFileSize, totalBytesTransferred);
        }
    }

    private delegate int CopyProgressRoutine(
        long totalFileSize, long TotalBytesTransferred, long streamSize, 
        long streamBytesTransferred, int streamNumber, int callbackReason,
        IntPtr sourceFile, IntPtr destinationFile, IntPtr data);

    [SuppressUnmanagedCodeSecurity]
    [DllImport("Kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
    private static extern bool CopyFileEx(
        string lpExistingFileName, string lpNewFileName,
        CopyProgressRoutine lpProgressRoutine,
        IntPtr lpData, ref bool pbCancel, int dwCopyFlags);
}

public delegate CopyFileCallbackAction CopyFileCallback(
    FileInfo source, FileInfo destination, object state, 
    long totalFileSize, long totalBytesTransferred);

public enum CopyFileCallbackAction
{
    Continue = 0,
    Cancel = 1,
    Stop = 2,
    Quiet = 3
}

[Flags]
public enum CopyFileOptions
{
    None = 0x0,
    FailIfDestinationExists = 0x1,
    Restartable = 0x2,
    AllowDecryptedDestination = 0x8,
    All = FailIfDestinationExists | Restartable | AllowDecryptedDestination
}

MSDN Magazine には、より広範な説明があります。

于 2012-08-08T19:45:27.043 に答える
1

何週間にもわたる調査、テスト、苦痛の末、私はついに実用的な解決策を見つけたようで、この方法をWin Server2008R2で利用可能なMicrosoftRobocopyコマンドSystem.IO.File.Copyの呼び出しに置き換えることにしました。最初の試行からうまく機能しているようです。これにより、車輪の再発明ではなく、自分のニーズに合わせて設計されたテスト済みのテクノロジーを使用していることに安心できます。とにかくあなたの答えとコメントをみんなに感謝します。

于 2012-11-04T15:57:37.607 に答える