dart中的主子isolate带参通信(主isolate - 多个子isolate)

鉴于前文是主isolate和一个子isolate间的通信,这里再给出个主isolate和多个isolate之间的通信例子,这个例子给出的是2个子isolate。

这里也记录为啥由单子isolate向多子isolate转变。原因:由于项目中主要耗时的任务分为两类,一个是数据库处理,另一个是http相关的处理,之前我偷懒,就把这两个都放到同一个子isolate中去处理。然后,我就遇到了主子isolate通信阻塞的问题。当然是我这边的锅,前文中的例子,主子isolate间的通信是主发给子,子处理完再发回给主,再关闭port,如果子isolate中发生了异常、卡死等的问题,则主无法再向子发出处理要求。因此可将这两者分开以减少两者间的影响。

注:在主子isolate通信时,http返回的内容不能直接回传,会报错Invalid argument(s): Illegal argument in isolate message: object is unsendable - Library:'dart:async' Class: _ControllerStream@4048458 (see restrictions listed at SendPort.send() documentation for more information)
因为 SendPort.send() 对可发送的对象有限制,可发送的类型有null、num、bool、String、List、Map、SendPort

import 'dart:isolate';
import 'dart:convert';
import 'package:http/http.dart' as http;

// 模拟数据库操作
class DatabaseService {
  static Future<dynamic> performDatabaseOperation(dynamic data) async {
    // 这里可以实现具体的数据库操作
    await Future.delayed(Duration(seconds: 1));
    return 'Database operation result: $data';
  }
}

// 处理数据库操作的子 Isolate 入口函数
void databaseIsolateEntry(SendPort mainSendPort) {
  final receivePort = ReceivePort();
  mainSendPort.send([receivePort.sendPort, 'dbIsolate']);

  receivePort.listen((message) async {
    final sendPort = message[0];
    final data = message.sublist(1);
    final result = await DatabaseService.performDatabaseOperation(data);
    sendPort.send(result);
  });
}

// 处理 HTTP 调用的子 Isolate 入口函数
void httpIsolateEntry(SendPort mainSendPort) {
  final receivePort = ReceivePort();
  mainSendPort.send([receivePort.sendPort, 'httpIsolate']);

  receivePort.listen((message) async {
    final sendPort = message[0];
    final data = message.sublist(1);
    try {
      final response = await http.get(Uri.parse(data[0]));
      if (response.statusCode == 200) {
        sendPort.send(json.decode(response.body));
      } else {
        sendPort.send('HTTP request failed with status: ${response.statusCode}');
      }
    } catch (e) {
      sendPort.send('Error making HTTP request: $e');
    }
  });
}

class IsolateService {
  static Isolate? _databaseIsolate;
  static Isolate? _httpIsolate;
  static SendPort? _databaseSendPort;
  static SendPort? _httpSendPort;
  static final ReceivePort _receivePort = ReceivePort();

  static Future<void> init() async {
    _databaseIsolate = await Isolate.spawn(databaseIsolateEntry, _receivePort.sendPort);
    _httpIsolate = await Isolate.spawn(httpIsolateEntry, _receivePort.sendPort);

    int initializedCount = 0;
    await for (var message in _receivePort) {
      if (message[0] is SendPort && message[1] == "dbIsolate") {
        _databaseSendPort = message[0];
        initializedCount++;
      } else if (message[0] is SendPort && message[1] == "httpIsolate") {
        _httpSendPort = message[0];
        initializedCount++;
      }
      if (initializedCount == 2) {
        break;
      }
    }
  }

  static Future<dynamic> sendToDatabase(dynamic message) async {
    if (_databaseSendPort == null) {
      throw Exception('Database isolate is not initialized. Call init() first.');
    }
    final responseReceivePort = ReceivePort();
    _databaseSendPort!.send([responseReceivePort.sendPort, ...message]);

    try {
      final response = await responseReceivePort.first;
      print("mainIsolate has get the response from database isolate: $response");
      responseReceivePort.close();
      return response;
    } catch (e) {
      print('Error receiving response from database isolate: $e');
      return null;
    }
  }

  static Future<dynamic> sendToHttp(dynamic message) async {
    if (_httpSendPort == null) {
      throw Exception('HTTP isolate is not initialized. Call init() first.');
    }
    final responseReceivePort = ReceivePort();
    _httpSendPort!.send([responseReceivePort.sendPort, ...message]);

    try {
      final response = await responseReceivePort.first;
      print("mainIsolate has get the response from http isolate: $response");
      responseReceivePort.close();
      return response;
    } catch (e) {
      print('Error receiving response from http isolate: $e');
      return null;
    }
  }

  static void dispose() {
    _receivePort.close();
    _databaseIsolate?.kill(priority: Isolate.immediate);
    _httpIsolate?.kill(priority: Isolate.immediate);
  }
}

void main() async {
  await IsolateService.init();

  // 向数据库子 Isolate 发送消息
  final databaseResult = await IsolateService.sendToDatabase(['test data']);
  print('Database result: $databaseResult');

  // 向 HTTP 子 Isolate 发送消息
  final httpResult = await IsolateService.sendToHttp(['https://jsonplaceholder.typicode.com/todos/1']);
  print('HTTP result: $httpResult');

  IsolateService.dispose();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值