Windows (7 以降) マシンと NFS マウントされた Unix ベースのサーバーの間でファイルの読み取り/書き込みを行う C# アプリケーション (.NET Framework 4.0 以下 (つまり、Read/WriteAsync なし) に限定) を作成しています。 .
クライアント マシンはモバイルであり、定期的にネットワークから切断されることが想定されています。このため、アプリケーションを強化して、読み取りまたは書き込み操作の途中で (できれば偶然に) 切断を適切に処理できるようにしたいと考えています。
タイムアウトが発生したかどうかを追跡するために、非同期で読み取り (または書き込み) を行い、 によって返された を使用AsyncWaitHandle
しIAsyncResult
ます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
も無期限にハングすることに注意してください。