程序在访问断开连接的驱动器时冻结30秒

时间:2010-01-18 20:33:34

标签: delphi

我有这段代码让我发疯。

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秒。

代码位于我创建的组件的构造函数中。

如何在不等待那么久的情况下检查驱动器?

3 个答案:

答案 0 :(得分:5)

首先,您必须意识到等待。访问尚未缓存的可移动媒体是一项昂贵的操作,取决于许多不同的东西(驱动程序,制造商,媒体质量,操作系统版本,服务包,安装的防病毒等)。

一旦你达成了这个条款,你不必让你的应用程序实际冻结。我这里没有Delphi,但我会做的是

  • 创建新的TThreadedObject并将DiskInDrive逻辑放入其执行方法
  • 使用变量设置/获取此结果
  • 启用/禁用相应的可视控件。

这样你仍然需要等待,但你的应用程序不会没有响应。您甚至可以添加取消操作的选项(如果操作需要很长时间才能完成。)

答案 1 :(得分:3)

据我所知,在Windows尝试访问网络驱动器时,使用网络驱动器执行操作可能会锁定调用线程,这是不可避免的。这是Joel Spolsky谈论的leaky abstractions之一。

您最好的选择是从单独的线程进行驱动器检查,以便它不会锁定UI。 (Delphi 2009的泛型或Jon Schemitz'MsgWaits库可以简化必要的多线程代码。)

答案 2 :(得分:1)

使用工作线程在delphi中创建一个组件,并通过调用从池创建或获取工作线程的例程来替换对此函数的调用,并开始这项工作。然后如果代码超时,则返回FALSE。因此,如果磁盘超时,则磁盘不在驱动器中。

代码将在其时间内完成,并将线程返回到池中。