【问题标题】:Program freezes 30 sec while accessing a disconnected drive程序在访问断开连接的驱动器时冻结 30 秒
【发布时间】:2010-01-19 18:11:02
【问题描述】:

我有这段代码让我发疯。

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

代码在我制作的一个组件的构造函数中。

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

【问题讨论】:

  • 你不能;这适用于本地和网络资源。另请参阅此问题的答案:stackoverflow.com/questions/1438923/… 在单独的线程中解决此问题(如果您检查多个设备:每个线程一个设备)

标签: delphi


【解决方案1】:

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

一旦您接受了这一点,您就不必让您的应用程序真正冻结。我这里没有 Delphi,但我会做的是

  • 新建一个TThreadedObject 并将DiskInDrive 逻辑放入其Execute 方法中
  • 使用变量设置/获取此结果
  • 启用/禁用适当的可视化控件。

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

      代码将按时完成,并将线程返回到池中。

      【讨论】:

      • 代码已经在我做的一个组件的构造函数中了。
      猜你喜欢
      • 2014-09-12
      • 2023-03-04
      • 1970-01-01
      • 2018-05-04
      • 2011-01-05
      • 1970-01-01
      • 2017-07-21
      • 1970-01-01
      • 2020-02-02
      相关资源
      最近更新 更多