我有一个自定义列表控件,它显示带有图像缩略图的项目。每个列表项都给出了文件的完整路径,并使用 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;
}
}
}
编辑:从 Dispose() 方法中删除了 currentFileStream 的处理。
编辑#2:从 LoadImage() 函数中删除了 currentFileStream 的处理。它可能不应该存在,因为文件读取可能正在进行中并且在操作期间无法关闭。无论何时调用 FileReadComplete 回调,它都会被释放。