代码之家  ›  专栏  ›  技术社区  ›  KOGI

如何取消/中止Dart中的区域?

  •  1
  • KOGI  · 技术社区  · 7 年前

    我有一个http web服务器,试图检测长时间运行的请求并中止它们。以下代码在超时时成功返回到客户端,但异步区域仍继续运行到完成。 我怎么能 杀死 请求处理程序?

    var zone = runZoned(() {
      var timer = new Timer(new Duration(seconds: Config.longRequestTimeoutSeconds), () {
        if (!completer.isCompleted) { // -- not already completed
          log.severe('request timed out');
          // TODO: This successfully responds to the client early, but it does nothing to abort the zone/handler that is already running.
          //       Even though the client will never see the result (and won't have to wait for it), the zone/handler will continue to run to completion as normal.
          // TODO: Find a way to kill/abort/cancel the zone
          completer.complete(new shelf.Response(HttpStatus.SERVICE_UNAVAILABLE, body: 'The server timed out while processing the request'));
        }
      });
    
      return innerHandler(request) // -- handle request as normal (this may consist of several async futures within)
        .then((shelf.Response response) {
          timer.cancel(); // -- prevent the timeout intercept
          if (!completer.isCompleted) { // -- not already completed (not timed out)
            completer.complete(response);
          }
        })
        .catchError(completer.completeError);
    });
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   lrn    7 年前

    除了代码本身,任何东西都不能杀死正在运行的代码。如果您希望代码是可中断的,您需要某种方式来告诉它,并且代码本身需要终止(可能通过抛出错误)。在这种情况下 innerHandler 需要能够在请求时中断自身。如果不是你的代码,那可能不可能。

    可以 编写一个区域,在设置标志时停止异步事件的执行(通过修改 Zone.run 等等),但您必须对此非常小心—如果您开始丢弃异步事件,可能永远不会得到异步最终阻塞和释放资源。因此,不建议将其作为一般解决方案,仅适用于愿意进行手动资源管理的非常谨慎的人员。

    推荐文章