Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Concurrency 访问电子表格时锁定脚本无效_Concurrency_Google Apps Script_Google Spreadsheet Api - Fatal编程技术网

Concurrency 访问电子表格时锁定脚本无效

Concurrency 访问电子表格时锁定脚本无效,concurrency,google-apps-script,google-spreadsheet-api,Concurrency,Google Apps Script,Google Spreadsheet Api,我的问题是如何确保并发访问时不会丢失数据 我已将脚本发布为web应用程序。我想在数据表中添加新行。处理“提交”按钮的函数如下所示: function onButtonSubmit(e) { var app = UiApp.getActiveApplication(); var lock = LockService.getPublicLock(); while (! lock.tryLock(1000)) ; var ssheet = SpreadsheetApp.open

我的问题是如何确保并发访问时不会丢失数据

我已将脚本发布为web应用程序。我想在数据表中添加新行。处理“提交”按钮的函数如下所示:

function onButtonSubmit(e) {
  var app = UiApp.getActiveApplication();
  var lock = LockService.getPublicLock();
  while (! lock.tryLock(1000))
    ;
  var ssheet = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ssheet.getSheetByName(DATA_SHEET);
  var lastRow = sheet.getLastRow();
  var lastCol = sheet.getLastColumn();
  var rangeToInsert = sheet.getRange(lastRow+1, 1, 1, lastCol);
  var statText = rangeToInsert.getA1Notation();
  rangeToInsert.setValues(<some data from webapp form>);
  app.getElementById('statusLabel').setText(statText);
  lock.releaseLock();
  return app;
}
功能按钮提交(e){
var app=UiApp.getActiveApplication();
var lock=LockService.getPublicLock();
而(!lock.tryLock(1000))
;
var ssheet=电子表格应用程序openById(表格ID);
var sheet=ssSheet.getSheetByName(数据表);
var lastRow=sheet.getLastRow();
var lastCol=sheet.getLastColumn();
var rangeToInsert=sheet.getRange(lastRow+1,1,1,lastCol);
var statText=rangeToInsert.geta1表示法();
rangeToInsert.setValues();
app.getElementById('statusLabel').setText(statText);
锁。释放锁();
返回应用程序;
}
但这似乎不起作用。当我在一秒钟内打开两个表单并单击submit按钮时,它会在statsLabel中显示相同的范围,并将数据写入相同的范围。所以我丢失了一个表单中的数据

这个代码有什么问题?看起来tryLock()不会阻止脚本

有没有其他方法可以防止对工作表的并发写访问

while (! lock.tryLock(1000))
    ;
看起来有点可疑。请尝试以下方法:

  if (lock.tryLock(30000))  {
    // I got the lock!  Wo000t!!!11 Do whatever I was going to do!
  } else {
    // I couldn’t get the lock, now for plan B :(
    GmailApp.sendEmail(“admin@example.com”, “epic fail”,
        “lock acquisition fail!”);
  }

它可能值得一看,而不是使用
getLastRow()
/
setValues()

允许在电子表格中以原子方式追加一行;可以使用 即使脚本的多个实例同时运行,也是安全的 同时。以前,必须调用getLastRow(),然后写入 到那一排。但是如果脚本的两次调用同时运行 同时,它们可能都读取getLastRow()的相同值,并且 然后覆盖彼此的值


使用带锁的getLastRow()/setValues()时,必须插入此代码

SpreadsheetApp.flush();
// before
lock.releaseLock();

我想等到锁被另一个实例释放。如果它从未被释放呢?如果第一个用户离开他的计算机怎么办?你的策略应该是只在你需要写作的时候锁定,而且写作不应该花那么长时间,真的。如果你的竞争对手是两个以上的用户,你需要一个更好的解决方案,比如数据库。是的,一些数据库是更好的解决方案,但我必须在谷歌电子表格中这样做。无论如何,我可以在n次迭代后中断while循环,然后以错误消息结束。尝试写入新行时,我仅在提交按钮处理程序中使用锁定。我尝试了您的解决方案,但它不起作用。两个提交的表单几乎同时将数据写入同一行。谢谢,我将在明天尝试。这是比锁定更好的解决方案。似乎锁定web应用程序是一个很好的解决方案