当我在 GAS 中“睡觉”时会发生什么? (执行时间限制解决方法)

2023-11-25

在这背后(我承认不是那么多......)有趣的问题是一个关于我使用的解决方法的真正问题,但没有真正理解它是如何工作的。

首先简要描述我的用例,所有这一切都发生在侧边栏中显示的文档绑定 UiApp 中:

我必须在用 GAS 编写的邮件合并应用程序中创建并通过电子邮件发送数百个文档。当然,在不达到 5 分钟执行时间限制的情况下进行一批处理需要太长时间,因此我尝试了几种不同的解决方法来完成任务:

  1. 当我启动进程时,以及当我达到接近限制的预定义值时,我使用时间戳(存储在 ScriptProperties 中),我存储当前值(指针、有用的变量...)并返回到用户界面,要求用户继续(或不)。这工作得很好,但需要人工操作才能完成整个任务。
  2. 因此,我使用在第一个处理程序调用中创建的计时器触发器设置了一个解决方案,并且该触发器调用文档创建/发送函数。这也工作得很好,但触发器调用的函数无法与 UI 交互,因为似乎只有处理程序函数可以更新 UI。问题是我无法显示进度,也无法轻松显示进程何时结束。
  3. 然后我想起了不久前为了好玩而写的一个小应用程序:它是一个计时器,使用复选框作为服务器处理程序触发器(来自 Romain Vialard 很久以前在旧 Google 论坛上提出的想法),并决定尝试这个我的邮件发送过程中的诡计。

它工作得很好,每次调用我都会处理 40 个文档批次(大约 3 分钟),然后暂停一段时间,然后重新开始,直到完成。 每个调用都由 checkBox 链接的服务器处理程序触发,复选框本身在处理程序函数中发生更改,以这种方式创建自己的触发器。

我的问题(最后;-)是:知道整个过程可能需要 30 到 60 分钟,这可能有多精确?这些服务器处理程序函数如何/为什么被视为多进程,因为它们是从函数本身内部创建的?

我希望我足够清楚,(我对此表示怀疑,因为我的头脑有点混乱:-)

我在下面加入了时钟测试应用程序的代码,它给了我这个想法,它可能会让事情更容易理解。

function doGet() {
  var app = UiApp.createApplication().setTitle('Counter/Timer');
  var Panel = app.createAbsolutePanel().setStyleAttribute('padding','35');
  var counter = app.createHTML().setId('counter').setHTML('<B>Timer = wait</B>').setStyleAttribute('fontSize','40px');// set start display
  var clo = app.createTextBox().setName('clo').setId('clo').setValue('0').setVisible(false);//set start value in seconds
  var handler1 = app.createServerHandler('doSomething').addCallbackElement(Panel);
  var chk1 = app.createCheckBox('test1').addValueChangeHandler(handler1).setVisible(true).setId('chk1').setVisible(false);
  app.add(Panel.add(chk1).add(counter).add(clo));
  chk1.setValue(true,true);// start the process
  return app}

function doSomething(e) {
  var app = UiApp.getActiveApplication();
  var xx = Number(e.parameter.clo);
  var disp = app.getElementById('counter')
  xx++ ;// replace by xx-- to count downwards
  if(xx>600){ // 10 minutes timeout for example
  disp.setHTML('<B> GAME OVER ;-)</B>').setStyleAttribute('fontSize','80px').setStyleAttribute('color','RED')
  return app
  }
  var cnt = app.getElementById('clo').setValue(xx)
  disp.setHTML('<B>'+T(xx)+'</B>')
  Utilities.sleep(1000); // instead of sleeping do something !
// below comes the "active" part
  var chk1 = app.getElementById('chk1').setValue(false,false)
  var chk1 = app.getElementById('chk1').setValue(true,true)
  return app;
}

function T(val){
  var min = parseInt(val/60);
  var sec = val-(60*min);
  if(sec<10){sec='0'+sec}
  if(min<10){min='0'+min}
  var st = '>  '+min+':'+sec
  return st
}

enter image description here


服务器处理程序函数调用不是独立进程,因为它们“是从函数本身内部创建的”这一说法并不完全正确。

您已经设置了一个 checkBox 元素chk1与服务器处理程序doSomething。每当 复选框被选中,然后,一个事件派遣到服务器。 (...并且您的脚本每次都会导致这些事件chk1.setValue()呼叫)的checkBox并且周围的 UI 代码正在您的浏览器中运行 - 单击“显示源”或使用资源管理器查看 Google 服务器向您的浏览器提供的内容。 (警告 - 它被混淆了。但是您可能会识别出一些字符串,并从中识别出您的客户端代码。)

这是文档中告诉我们的内容类 服务器处理程序:

当调用 ServerHandler 时,它引用的函数将在 Apps 脚本服务器上以“新”脚本调用。

这是延长操作时间的关键:每个分派的事件都会导致调用doSomething()在一个全新的操作环境中 - 就像您在不同的浏览器中打开脚本编辑器,然后在脚本上单击“运行”一样。 “新鲜”脚本无法访问先前运行的 var 值...但它也有自己的一组操作限制,包括计时器。

PS:您应该使用 Lock 确保服务器端处理程序是“线程安全的”,因为您正在访问可能被多个实例访问的共享资源doSomething()打回来。与此相关的是,此脚本可能会达到另一个限制:

Screenshot - error

只是为了好玩,我评论了.setVisible(false) on chk1,因此复选框将可见。然后我快速点击了它几十次。时间显示乱了,最终弹出了上述错误。 (几分钟后)当然,这是一种人为的情况,但仍然是一种很容易避免的错误状态。

PPS:我想知道是否可以使用相同的技术来分派多个并行服务器端处理程序,从而减少完成整个工作所需的时间?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当我在 GAS 中“睡觉”时会发生什么? (执行时间限制解决方法) 的相关文章

随机推荐

  • malloc 未定义

    我目前正在重写链表模块 并且收到一些奇怪的错误 在两个 IDE Netbeans 和 Visual Studio Express 中 我收到一条警告 malloc未定义 并且在 linkedlist c 文件中找到的函数也未定义 下面是我的
  • 如何使用 javascript_include_tag 获取文件夹中的所有脚本

    我想用javascript include tag使用递归获取所有与视图相关的脚本 将其放置在public javascripts views 我想javascript include tag views recursive gt true
  • Java 8矩阵*向量乘法

    我想知道是否有一种更简洁的方法可以在 Java 8 中使用流执行以下操作 public static double multiply double matrix double vector int rows matrix length in
  • 如何在我的 HTTP 请求中使用带有身份验证的代理?

    我有一个代理 IP 地址 还需要用户名和密码 当我尝试使用它们访问网页时 我收到 需要代理身份验证 我发现了 2016 年的另一篇 Stackoverflow 帖子 以及这个已关闭的 Github 问题 但他们没有提供任何有用的东西 代理
  • 使用 ASP NET MVC 4 和 webapi 自定义 http 处理程序和路由处理程序

    我正在开发 ASPNET MVC 4 和 WebApi webapi 方法将由移动设备使用 我们需要保护服务的安全 而我们正在使用的是以某种特定方式加密数据 现在 我需要在到达控制器之前解密该调用 如果解密的信息有效 它应该像平常一样继续发
  • Apache 2.4“..身份验证失败..:密码不匹配”

    我在 Windows Server 2008 R2 中运行 Apache 2 4 我正在尝试用密码保护子目录 并在 Apache 2 0 中成功做到了这一点 升级后 我采纳了 Apache 的建议 并尝试将身份验证配置放入 httpd co
  • 如何防止android对讲说话seekbar进度

    我有一个自定义控件扩展SeekBar 其中我已经覆盖了onInitializeAccessibilityNodeInfo如下 Override public void onInitializeAccessibilityNodeInfo Ac
  • 在C#中用鼠标画线的正确方法是什么

    这是我的绘图代码 用于用鼠标在图表上绘制自定义线条 你能帮我以正确的方式做吗 namespace Grafi public partial class Form1 Form bool isDrawing false Point prevPo
  • 如何确定数组是否包含单独数组中的所有整数

    我在学校的计算机科学课上 我被这个问题困扰了 甚至无法真正想出如何解决它的想法 这里是逐字逐句 编写一个名为的静态方法contains接受两个整数数组 a1 和 a2 作为参数 并返回一个布尔值 指示 a2 的元素序列是否出现在 a1 中
  • DB Plugin 未在 Play 2.0 中注册

    我刚刚开始使用 play 并且修改了执行 SQL 读取的方式 现在收到以下错误 Exception DB plugin is not registered 我这个类的代码是 package models import play api db
  • 从 RichTextBox 复制选定的文本

    我在网上搜索过 但找不到从文件中复制 剪切 粘贴所选文本的方法RichTextBox 就连MSDN也没有给出答案 他们提供的代码不起作用 Copy 似乎仅适用于 TextBox 不适用于 RichTextBox 如果我复制这个方法 Clip
  • Pygame Joystick.get_axis() 始终返回零

    我购买了罗技游戏手柄 F310 来远程控制机器人 我在 Linux Mint 版本 18 Sarah 上使用 Pygame 版本 1 9 1 Python 版本 2 7 11 作为检查操纵杆功能的简单测试 我编写了这个简短的脚本 用于输出不
  • 在 asp.net 中创建自定义 .config 文件 [关闭]

    Closed 这个问题需要多问focused 目前不接受答案 有没有一种方法可以在 asp net 中创建 blah config 文件 并以与访问常规 web config 文件中的项目相同的方式访问节点的名称 值对 这个想法是不必为此编
  • 使用 one-hot 代码的 Tensorflow 混淆矩阵

    我使用 RNN 进行多类分类 这是我的 RNN 主要代码 def RNN x weights biases x tf unstack x input size 1 lstm cell rnn BasicLSTMCell num unit f
  • ES6 Promises 和 PEP3148 Futures 的连锁差异

    我对 ES6 Promises 和 PEP3148 Futures 实现差异的推理有些困惑 在 Javascript 中 当 Promise 与另一个 Promise 一起解决时 一旦解决或拒绝 外部 Promise 就会继承 内部 Pro
  • 使用 JOIN 而不是 WHERE 进行过滤

    在 SQL MSSQL Oracle 等 中 当连接表时 向 JOIN 语句添加过滤器而不是在 WHERE 子句中添加过滤器有什么好处 i e SELECT FROM X INNER JOIN Y ON X A Y A WHERE X B
  • 如何在 Excel VBA 中检查或取消多个待处理的 application.ontime 事件?

    我正在使用 Application Ontime 事件从单元格中提取时间字段 并安排一个子例程在那时运行 我的 Application Ontime 事件在 Workbook BeforeSave 事件上运行 因此 如果用户 更改所需时间
  • 在haskell中迭代字符串并用子字符串替换单个字符

    我正在尝试学习一些 Haskell 但发现很难 我的一些问题 当前的项目 我的想法是我必须遍历一个字符串并替换某些字符 带有新的子字符串 例如 如果我有一个字符串 FLXF 并且我想替换每个 F 如果子字符串名为 FLF 则结果应为 FLF
  • 如何使用 python 更新 mysql,其中字段和条目来自字典?

    我正在尝试创建一个可重用的 mysql 语句 用于从字典进行更新 其中键是数据库字段 进入该字段的数据是字典中与其关联的值 创建插入 mysql 的函数时这很容易 因为它只涉及两个列表 现在 我需要分解这些列表 这是我必须处理的事情 fie
  • 当我在 GAS 中“睡觉”时会发生什么? (执行时间限制解决方法)

    在这背后 我承认不是那么多 有趣的问题是一个关于我使用的解决方法的真正问题 但没有真正理解它是如何工作的 首先简要描述我的用例 所有这一切都发生在侧边栏中显示的文档绑定 UiApp 中 我必须在用 GAS 编写的邮件合并应用程序中创建并通过