2

我正在编写一个 C# 应用程序(仅限于 .NET 框架 4.0 或更低版本(即没有 Read/WriteAsync)),负责在 Windows(7 或更高版本)机器和基于 NFS 的基于 Unix 的服务器之间读取/写入文件.
客户端机器是移动的,预计会定期与网络断开连接。正因为如此,我希望加强我的应用程序以优雅地处理读取或写入操作中间的断开连接(希望是偶然的)。

为了跟踪是否发生超时,我异步读取(或写入)并使用返回的AsyncWaitHandleby :IAsyncResultFileStream.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