我有这段代码让我发疯。
FUNCTION DiskInDrive(CONST DriveNumber: Byte): BOOLEAN;
VAR ErrorMode : Word;
BEGIN
RESULT:= FALSE;
ErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS);
TRY
if DiskSize(DriveNumber) <> -1 { %%%% THIS IS VERY SLOW IF THE DISK IS NOT IN DRIVE !!!!!! }
THEN RESULT:= TRUE;
FINALLY
SetErrorMode(ErrorMode);
END;
END;
它检查磁盘是否可以使用(以及提供的驱动器号是否与有效磁盘相对应)。 问题是,当我尝试访问断开连接的网络驱动器(映射为驱动器的网络文件夹)时,它会冻结大约10-30秒。
代码位于我创建的组件的构造函数中。
如何在不等待那么久的情况下检查驱动器?
答案 0 :(得分:5)
首先,您必须意识到有等待。访问尚未缓存的可移动媒体是一项昂贵的操作,取决于许多不同的东西(驱动程序,制造商,媒体质量,操作系统版本,服务包,安装的防病毒等)。
一旦你达成了这个条款,你不必让你的应用程序实际冻结。我这里没有Delphi,但我会做的是
TThreadedObject
并将DiskInDrive
逻辑放入其执行方法这样你仍然需要等待,但你的应用程序不会没有响应。您甚至可以添加取消操作的选项(如果操作需要很长时间才能完成。)
答案 1 :(得分:3)
据我所知,在Windows尝试访问网络驱动器时,使用网络驱动器执行操作可能会锁定调用线程,这是不可避免的。这是Joel Spolsky谈论的leaky abstractions之一。
您最好的选择是从单独的线程进行驱动器检查,以便它不会锁定UI。 (Delphi 2009的泛型或Jon Schemitz'MsgWaits库可以简化必要的多线程代码。)
答案 2 :(得分:1)
使用工作线程在delphi中创建一个组件,并通过调用从池创建或获取工作线程的例程来替换对此函数的调用,并开始这项工作。然后如果代码超时,则返回FALSE。因此,如果磁盘超时,则磁盘不在驱动器中。
代码将在其时间内完成,并将线程返回到池中。