菜鸟科技网

易语言延时命令为何不精确?

下面我将详细解释这个命令,并提供一些示例和注意事项。

易语言延时命令为何不精确?-图1
(图片来源网络,侵删)

核心命令:延时()

延时() 命令会让当前线程(也就是你的程序)暂停执行指定的毫秒数。

命令格式

.版本 2
.程序集 窗口程序集_启动窗口
.子程序 __启动窗口_创建完毕
    .局部变量 i, 整数型
    ' 输出提示信息
    信息框 (“程序即将开始延时...”, 0, )
    ' 延时 3 秒 (3000 毫秒)
    延时 (3000)
    ' 延时结束后,输出信息
    信息框 (“3秒延时已结束!”, 0, )
    ' --- 循环延时示例 ---
    信息框 (“现在开始一个循环,每次延时1秒,共循环5次”, 0, )
    .计次循环首 (5, i)
        编辑框1.内容 = “正在执行第 ” + 到文本(i) + “ 次循环...”
        ' 每次循环延时 1000 毫秒 (1秒)
        延时 (1000)
    .计次循环尾 ()
    信息框 (“循环结束!”, 0, )

参数说明

  • 参数:一个“整数型”的数值,代表需要延时的毫秒数
    • 1000 毫秒 = 1
    • 500 毫秒 = 5
    • 100 毫秒 = 1

返回值

  • 延时() 命令在执行完成后会返回一个“逻辑型”值:
    • :表示延时正常结束。
    • :表示延时被中断(在延时过程中,用户关闭了程序窗口)。

重要概念:延时() 的工作原理(阻塞式)

这是理解 延时() 命令最关键的一点。

延时() 是一个“阻塞式”(Blocking)命令,当你的程序执行到 延时(3000) 时:

  1. 当前线程暂停:程序会立即“卡住”在这一行,不再继续执行下面的代码。
  2. 不响应界面:整个程序窗口会进入“假死”状态,用户无法点击按钮、输入文字、移动窗口等,程序完全失去了响应能力。
  3. 等待时间结束:程序会像“死机”一样,默默地等待 3000 毫秒(3秒)过去。
  4. 恢复执行:3 秒后,程序才会“活”过来,继续执行 延时() 下面的代码。

示例:演示阻塞效果

创建一个易语言程序,界面有一个按钮“开始延时”和一个编辑框。

易语言延时命令为何不精确?-图2
(图片来源网络,侵删)
.版本 2
.程序集 窗口程序集_启动窗口
.子程序 _按钮_开始延时_被单击
    .局部变量 i, 整数型
    ' 清空编辑框
    编辑框1.内容 = “”
    ' 提示用户
    信息框 (“点击“确定”后,程序将延时5秒,期间窗口将无响应!”, 0, )
    ' 开始一个循环,每次延时1秒,共5次
    .计次循环首 (5, i)
        编辑框1.内容 = “已延时 ” + 到文本(i) + “ 秒...”
        ' 每次延时 1 秒
        延时 (1000)
    .计次循环尾 ()
    ' 延时结束
    编辑框1.内容 = “延时全部结束!”
    信息框 (“延时结束!”, 0, )

运行这个程序,你会发现:

  • 点击按钮后,立即弹出信息框。
  • 点击信息框的“确定”后,程序会卡住 5 秒,在这 5 秒内,你无法移动窗口、无法点击其他任何地方,编辑框的内容会每秒更新一次,但整个程序界面是“冻结”的。

替代方案:非阻塞式延时(推荐)

在很多情况下,我们不希望整个程序卡住,而是希望“在后台等待的同时,窗口依然可以响应”,这时就需要使用非阻塞式的延时方法。

核心思想是:记录开始时间,然后在循环中不断检查当前时间是否已经超过了设定的延时时间。

使用 取现行时间()判断循环首()

.版本 2
.程序集 窗口程序集_启动窗口
.子程序 _按钮_非阻塞延时_被单击
    .局部变量 开始时间, 长整型
    .局部变量 已过去时间, 长整型
    .局部变量 目标延时, 整数型
    ' 设置目标延时为5秒 (5000毫秒)
    目标延时 = 5000
    ' 记录程序开始执行此操作时的精确时间(毫秒级)
    开始时间 = 取现行时间 ()
    ' 输出提示
    编辑框1.内容 = “非阻塞延时开始!窗口依然可以响应。”
    信息框 (“非阻塞延时开始!你可以尝试移动窗口或点击其他按钮。”, 0, )
    ' 进入一个循环,直到时间到达为止
    .判断循环首
        ' 获取当前时间,并计算与开始时间的时间差(毫秒)
        已过去时间 = 取现行时间 () - 开始时间
        ' 如果过去的时间大于或等于我们设定的目标延时,就退出循环
        .(已过去时间 ≥ 目标延时)
            跳出循环 ()
        .否则
            ' 如果时间还没到,就让程序“休息”一小会儿,避免CPU占用过高
            ' 10毫秒是一个比较合理的值,既能保持响应,又不会占用太多资源
            延时 (10)
        .如果结束
    .判断循环尾
    ' 循环结束后,延时完成
    编辑框1.内容 = “非阻塞延时结束!”
    信息框 (“非阻塞延时结束!”, 0, )

使用时钟组件(更简单直观)

这是实现非阻塞延时的另一种非常流行且简单的方法。

易语言延时命令为何不精确?-图3
(图片来源网络,侵删)

步骤:

  1. 在易语言窗口上拖入一个时钟组件(时钟1)。
  2. 设置时钟的“周期”属性为你想要的最小时间单位,100 (毫秒)。
  3. 在按钮的点击事件中,启动时钟并设置一个计数器。
  4. 在时钟的周期事件中,让计数器加一,并判断是否达到延时目标。
.版本 2
.程序集 窗口程序集_启动窗口
.程序集变量 延时计数器, 整数型
.程序集变量 目标秒数, 整数型
.子程序 _按钮_时钟延时_被单击
    ' 设置延时目标为5秒
    目标秒数 = 5
    ' 重置计数器
    延时计数器 = 0
    ' 清空编辑框
    编辑框1.内容 = “”
    ' 启动时钟
    时钟1.时钟周期 = 100 ' 每100毫秒触发一次
    时钟1.启用 = 真
.子程序 _时钟1_周期事件
    ' 每次时钟触发,计数器加1
    延时计数器 = 延时计数器 + 1
    ' 更新界面显示已过去的时间(秒)
    编辑框1.内容 = “已过去:” + 到文本(延时计数器 / 10) + “ 秒”
    ' 判断是否达到目标 (5秒 = 50个100毫秒)
    .(延时计数器 ≥ 目标秒数 × 10)
        ' 达到目标,停止时钟
        时钟1.启用 = 假
        ' 弹出提示
        信息框 (“时钟非阻塞延时结束!”, 0, )
        编辑框1.内容 = “时钟延时结束!”
    .如果结束

总结与对比

方法 命令/组件 原理 优点 缺点 适用场景
阻塞式延时 延时() 暂停整个线程,不响应任何事件。 代码极其简单,逻辑清晰。 程序界面会卡死,无响应,用户体验差。 简单的脚本、后台任务、对实时性要求不高的场景。
非阻塞式延时1 取现行时间() + 判断循环首() 通过计算时间差来控制循环,循环内用小延时释放CPU。 程序保持响应,不卡顿,CPU占用可控。 代码比 延时() 稍复杂,需要手动管理循环。 需要在延时的同时执行其他操作,或需要保持界面响应的绝大多数场景。
非阻塞式延时2 时钟 组件 利用系统时钟周期性触发事件来计时。 代码逻辑清晰,易于理解,与界面结合紧密。 需要额外的组件,计时精度受时钟周期限制。 游戏、动画、需要周期性更新界面的应用。

推荐:

  • 如果只是想让程序“停一下”,不关心界面是否卡死,用 延时()
  • 如果希望程序在延时的同时,窗口还能正常工作(比如显示进度条、允许用户取消等),强烈推荐使用非阻塞式延时,特别是 取现行时间() 的方法。
分享:
扫描分享到社交APP
上一篇
下一篇