如何从 dart isolate 获取多条消息?

How can I get multiple messages from dart isolate?

如何从 dart isolate 获取多条消息?

我正在尝试 create an excel file 并希望在 隔离 中对该文件执行 some operation。在对该文件进行操作之前,我想 return 向主要隔离区发送一条消息,即创建了 excel 文件。

这是函数 isolate :

foo(String filePath){
    // create excel file
    var bytes = File(filePath).readAsBytesSync();
    var excel = Excel.decodeBytes(bytes);

    //HERE I WANT TO SEND THE MESSAGE THAT CREATING EXCEL FILE IS DONE

    // some operatoin on excel file
    var result = doSomeOperation(excel);
    return result;
}

主要隔离代码:

var result = await compute(foo, filePath);

我应该怎么做才能在实际结果到来之前获得创建文件消息?

对于 excel,我正在使用 excel: ^2.0.0-null-safety-3 包。

只计算returns一个结果。如果你想将多个 'events' 传递回主隔离,那么你需要使用完整的隔离逻辑(带有 sendPort 和 receivePort)。

例如,以下代码在隔离中运行,并下载文件,同时发出 float 值来表示进度,可能是 String 来指示日志消息,然后是 bool 表示完成后成功或失败。

  Future<void> isolateDownload(
      DownloadRequest request) async {
    final sendPort = request.sendPort;
    if (sendPort != null) {
      var success = false;
      var errorMessage = '';
      var url = Uri.parse('a_url_based_on_request');
      IOSink? out;
      try {
        http.StreamedResponse response =
            await http.Client().send(http.Request('GET', url));
        if (response.statusCode == 200) {
          var filePath =
              join(request.destinationDirPath, '${request.fileName}.ZIP');
          var contentLength = response.contentLength;
          var bytesLoadedUpdateInterval = (contentLength ?? 0) / 50;
          var bytesLoaded = 0;
          var bytesLoadedAtLastUpdate = 0;
          out = File(filePath).openWrite();
          await response.stream.forEach((chunk) {
            out?.add(chunk);
            bytesLoaded += chunk.length;
            // update if enough bytes have passed since last update
            if (contentLength != null &&
                bytesLoaded - bytesLoadedAtLastUpdate >
                    bytesLoadedUpdateInterval) {
              sendPort.send(bytesLoaded / contentLength);
              bytesLoadedAtLastUpdate = bytesLoaded;
            }
          });
          success = true;
          if (contentLength != null) {
            sendPort.send(1.0); // send 100% downloaded message
          }
        } else {
          errorMessage =
              'Download of ${request.fileName} '
              'received response ${response.statusCode} - ${response.reasonPhrase}';
        }

      } catch (e) {
        errorMessage = 'Download of ${request.chartType}:${request.chartName} '
            'received error $e';
      } finally {
        await out?.flush();
        await out?.close();
        if (errorMessage.isNotEmpty) {
          sendPort.send(errorMessage);
        }
        sendPort.send(success);
      }
    }
  }

生成隔离的代码然后简单地检查传递给它的消息的类型以确定操作。

  Future<bool> _downloadInBackground(
      DownloadRequest request) async {
    var receivePort = ReceivePort();
    request.sendPort = receivePort.sendPort;
    var isDone = Completer();
    var success = false;
    receivePort.listen((message) {
      if (message is double) {
        showUpdate(message);
      }
      if (message is String) {
        log.fine(message); // log error messages
      }
      if (message is bool) {
        success = message; // end with success or failure
        receivePort.close();
      }
    }, onDone: () => isDone.complete()); // wraps up
    await Isolate.spawn(isolateDownload, request);
    await isDone.future;
    return success;
  }