2

Windows (7 以降) マシンと NFS マウントされた Unix ベースのサーバーの間でファイルの読み取り/書き込みを行う C# アプリケーション (.NET Framework 4.0 以下 (つまり、Read/WriteAsync なし) に限定) を作成しています。 .
クライアント マシンはモバイルであり、定期的にネットワークから切断されることが想定されています。このため、アプリケーションを強化して、読み取りまたは書き込み操作の途中で (できれば偶然に) 切断を適切に処理できるようにしたいと考えています。

タイムアウトが発生したかどうかを追跡するために、非同期で読み取り (または書き込み) を行い、 によって返された を使用AsyncWaitHandleIAsyncResultますFileStream.BeginRead

private int PerformRead (FileStream readStream,
                         byte [] buffer,
                         int nBytes)
{
    IAsyncResult readResult = null;

    try
    {
        readResult = readStream.BeginRead
            (buffer, 0, nBytes, null, null);

        // If the read was completed, return # of bytes read.
        if (readResult.AsyncWaitHandle.WaitOne (1000))
        {
            return readStream.EndRead (readResult);
        }
        // Otherwise, the timeout has elapsed.
        else
        {
            throw new TimeoutException ();
        }
    }
    finally
    {
        if (null != readResult)
        {
            readResult.AsyncWaitHandle.Close ();
        }
    }
}

私の問題は、タイムアウトの場合にストリームをクリーンアップすることで発生します。接続が切断されている間、ストリームの呼び出しが無期限にハングするDispose()ようです。Close()これを解決するためCloseHandle()に、タイムアウト時にファイル ハンドルで明示的に Win32 を呼び出します。この機能は、接続が切断されている間もブロックされるようです。以下は、読み取りストリームの私の扱いを表しています。

private void ReadNewFile (string path,
                          byte [] buffer)
{
    IntPtr readHandle = IntPtr.Zero;
    FileStream readStream = null;
    try
    {
        readHandle = CreateFile (path
                                 0xc0000000,
                                 0,
                                 IntPtr.Zero,
                                 3,
                                 0x40000000,
                                 IntPtr.Zero);
        SafeFileHandle safeReadHandle = new SafeFileHandle (readHandle, true);
        if (safeReadHandle.IsInvalid)
        {
            throw new Exception ();
        }
        readStream = new FileStream (safeReadHandle,
                                     FileAccess.Read,
                                     4092,
                                     true);
        while (true)
        {
            // Read part of the file into the buffer.
            int bytesRead = PerformRead (readStream, buffer, buffer.Length);

            // If EOF reached, break.
            if (bytesRead == 0)
            {
                break;
            }
        }
    }
    catch (TimeoutException)
    {
        // NOTE: Hangs indefinitely if the network cable is unplugged.
        CloseHandle (readHandle);
    }
    finally
    {
        if (null != readStream)
        {
            // NOTE: Hangs indefinitely if both of the following are true:
            // - Network cable is unplugged (resulting in TimeoutException)
            // - The body of the caught TimeoutException is commented out.
            readStream.Close ();
        }
    }
}

使用できなくなったファイルの FileStream を適切に破棄するための推奨される方法はありますか? 接続が切断された場合、への呼び出しBeginReadも無期限にハングすることに注意してください。

4

0 に答える 0