画像のサムネイルを含む項目を表示するカスタム リスト コントロールがあります。各リスト項目にはファイルのフル パスが与えられ、FileStream.BeginRead を使用して非同期に読み取ります。ファイルの読み取りが完了したら、リスト コントロールを無効にする必要があります。
いつでもリストから項目をクリアして、別の項目を再入力することもできます。これにより、ファイルストリームの破棄を適切に処理する必要がある各項目で Dispose が呼び出されます (まだ非同期読み取りの途中である可能性があります)。
私が使用しているコードを表示します。別のファイルが非同期でロードされている最中に、新しいファイルを非同期でロードするリクエストが来る可能性があるこのような状況で、オブジェクトを呼び出してロックする適切な使用法がわかりません。
public string FileName { get; set; }
public Image Image { get; set; }
public Control Parent { get; set; }
private FileStream currentFileStream;
private byte[] buffer;
private object locker = new object();
private bool loading;
private bool disposed;
public void LoadImage(string fileName)
{
FileName = fileName;
lock (locker)
{
currentFileStream = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.Read);
buffer = new byte[currentFileStream.Length];
currentFileStream.BeginRead(buffer, 0, buffer.Length, FileReadComplete, currentFileStream);
loading = true;
}
}
private void FileReadComplete(IAsyncResult ar)
{
FileStream fileStreamComplete = (FileStream)ar.AsyncState;
lock (locker)
{
fileStreamComplete.EndRead(ar);
// If the finished FileStream is the more recent one requested
// And this item has not been disposed
if (fileStreamComplete == currentFileStream && !disposed)
{
try
{
loading = false;
Image = new Bitmap(currentFileStream);
currentFileStream.Close();
currentFileStream.Dispose();
Parent.Invalidate();
}
catch (Exception e)
{
}
finally
{
currentFileStream = null;
}
}
else
{
fileStreamComplete.Close();
fileStreamComplete.Dispose();
}
}
}
protected override void Dispose(bool disposing)
{
lock (locker)
{
base.Dispose(disposing);
if (!disposed)
{
if (disposing)
{
if (Image != null)
Image.Dispose();
}
disposed = true;
}
}
}
EDIT : Dispose() メソッドから currentFileStream の破棄を削除しました。
編集 #2 : LoadImage() 関数から currentFileStream の破棄を削除しました。ファイルの読み取りが進行中である可能性があり、操作中に閉じることができないため、おそらく存在しないはずです。FileReadComplete コールバックがいつ呼び出されても、破棄されます。