我正在尝试制作一种有效的扩展方法,该方法将允许根据为数据记录生成的文件名同时锁定和并发访问文件系统。
我已阅读Locking on an interned string?,但它并不能完全回答我关于效率的问题。
我有一个看起来像这样的扩展方法(仅剥离相关代码):
public static string GetImageUrl( this IStoredImage img, string path )
{
var filename = String.Format( @"{0}\{1}_{2}{3}",
path, img.Id, img.Version, img.FileExtension );
//
// If the file does not exist, create it in a
// double-checked lock.
//
if( !File.Exists( filename ) )
{
//
// Ensure that our string is unique to this method and
// the file name, and that it is a shared reference.
//
var lockStr = StringPool.GetString(
MethodBase.GetCurrentMethod().Name + filename );
lock( lockStr )
{
if( !File.Exists( filename ) )
{
byte[] bytes = img.GetImageBytes();
//
// ...Code to write the file to disk
//
}
}
}
return GetUrlFromPhysicalPath( filename );
}
IStoredImage
是在数据库中存储标头和元信息的对象。图像的实际二进制数据在一个 1:1 的链接表中。GetImageBytes()
用二进制数据完成记录的加载。这样做的想法是能够将图像缓存到磁盘以提高效率。一旦文件被写出,GetImageBytes()
在图像的缓存目录被删除或清除之前,永远不需要调用。
StringPool
是一个静态类,可确保您对相同的字符串值获得相同的引用,类似于实习,但更高效和可控。
关于这个问题:使用字符串作为锁是否比简单地使用 a 更能提高效率private static object LOCK = new object()
?我的直觉告诉我,按照我的方式进行操作将允许需要写出图像数据的多个线程同时运行(只要它们处理不同的文件名),而使用相同的 LOCK 引用会导致它们运行串行。
我已经尝试过Mutex
和其他一些东西,但你必须小心,因为命名互斥体中的反斜杠字符会造成严重破坏。我不喜欢有奇怪的无证行为的东西。
提前致谢。