Dart 隔离区(Isolate)详解
简介
Isolate 是 Dart 中实现并发的方式。每个 Isolate 都有自己的内存堆和事件循环,Isolate 之间通过消息传递进行通信。
基本概念
创建 Isolate
dart
import 'dart:isolate';
void isolateFunction(SendPort sendPort) {
// Isolate 中的计算
int result = complexComputation();
// 发送结果回主 Isolate
sendPort.send(result);
}
Future<void> main() async {
// 创建通信端口
ReceivePort receivePort = ReceivePort();
// 启动新的 Isolate
await Isolate.spawn(isolateFunction, receivePort.sendPort);
// 接收结果
final result = await receivePort.first;
print('Result: $result');
}
双向通信
dart
void isolateFunction(SendPort sendPort) {
// 创建接收端口
final receivePort = ReceivePort();
// 发送此 Isolate 的 SendPort 到主 Isolate
sendPort.send(receivePort.sendPort);
// 处理接收到的消息
receivePort.listen((message) {
if (message is int) {
final result = message * 2;
sendPort.send(result);
}
});
}
Future<void> main() async {
final receivePort = ReceivePort();
await Isolate.spawn(isolateFunction, receivePort.sendPort);
// 获取新 Isolate 的 SendPort
final SendPort sendPort = await receivePort.first;
// 发送数据并等待响应
sendPort.send(42);
final result = await receivePort.elementAt(1);
print('Result: $result');
}
数据传递
可传递的数据类型
dart
// 基本类型
sendPort.send(42);
sendPort.send('Hello');
sendPort.send(true);
// 集合
sendPort.send([1, 2, 3]);
sendPort.send({'a': 1, 'b': 2});
// SendPort
sendPort.send(anotherSendPort);
// 自定义类型(需要实现特定接口)
class TransferableData {
final int id;
final String data;
TransferableData(this.id, this.data);
// 转换为可传输格式
Map<String, dynamic> toMap() {
return {
'id': id,
'data': data,
};
}
// 从可传输格式恢复
factory TransferableData.fromMap(Map<String, dynamic> map) {
return TransferableData(
map['id'] as int,
map['data'] as String,
);
}
}
错误处理
异常捕获
dart
void isolateFunction(SendPort sendPort) {
try {
throw Exception('Something went wrong');
} catch (e) {
sendPort.send({'error': e.toString()});
}
}
Future<void> main() async {
final receivePort = ReceivePort();
try {
await Isolate.spawn(isolateFunction, receivePort.sendPort);
final result = await receivePort.first;
if (result is Map && result.containsKey('error')) {
print('Error in isolate: ${result['error']}');
}
} catch (e) {
print('Error spawning isolate: $e');
}
}
完整示例
dart
import 'dart:isolate';
import 'dart:math';
// 计算密集型任务
class ComputeTask {
final int start;
final int end;
ComputeTask(this.start, this.end);
Map<String, dynamic> toMap() => {
'start': start,
'end': end,
};
factory ComputeTask.fromMap(Map<String, dynamic> map) =>
ComputeTask(map['start'], map['end']);
}
// 计算结果
class ComputeResult {
final int sum;
final Duration duration;
ComputeResult(this.sum, this.duration);
Map<String, dynamic> toMap() => {
'sum': sum,
'duration': duration.inMilliseconds,
};
factory ComputeResult.fromMap(Map<String, dynamic> map) =>
ComputeResult(
map['sum'],
Duration(milliseconds: map['duration']),
);
}
// Isolate ���作函数
void computeIsolate(SendPort sendPort) {
final receivePort = ReceivePort();
sendPort.send(receivePort.sendPort);
receivePort.listen((message) {
if (message is Map) {
final task = ComputeTask.fromMap(message);
final stopwatch = Stopwatch()..start();
// 执行计算密集型任务
int sum = 0;
for (int i = task.start; i <= task.end; i++) {
sum += i;
// 模拟复杂计算
sum += sqrt(i).floor();
}
stopwatch.stop();
final result = ComputeResult(sum, stopwatch.elapsed);
sendPort.send(result.toMap());
}
});
}
class ComputeManager {
SendPort? _sendPort;
ReceivePort? _receivePort;
Isolate? _isolate;
Future<void> initialize() async {
_receivePort = ReceivePort();
_isolate = await Isolate.spawn(computeIsolate, _receivePort!.sendPort);
_sendPort = await _receivePort!.first;
}
Future<ComputeResult> compute(ComputeTask task) async {
if (_sendPort == null) {
throw StateError('ComputeManager not initialized');
}
final responsePort = ReceivePort();
_sendPort!.send(task.toMap());
final resultMap = await responsePort.first;
return ComputeResult.fromMap(resultMap);
}
void dispose() {
_receivePort?.close();
_isolate?.kill();
_sendPort = null;
_receivePort = null;
_isolate = null;
}
}
void main() async {
final manager = ComputeManager();
await manager.initialize();
// 执行多个计算任务
final tasks = [
ComputeTask(1, 1000000),
ComputeTask(1000001, 2000000),
ComputeTask(2000001, 3000000),
];
for (var task in tasks) {
try {
final result = await manager.compute(task);
print('Task ${task.start}-${task.end}:');
print('Sum: ${result.sum}');
print('Duration: ${result.duration.inMilliseconds}ms\n');
} catch (e) {
print('Error computing task: $e');
}
}
manager.dispose();
}
最佳实践
- 合理划分计算任务
- 注意数据传输开销
- 及时释放资源
- 处理好异常情况
- 避免过多的 Isolate
注意事项
- Isolate 之间不共享内存
- 注意数据序列化成本
- 合理控制 Isolate 数量
- 处理好生命周期
- 注意平台限制
总结
Isolate 是 Dart 中实现并发的重要机制,通过合理使用可以充分利用多核性能。理解并掌握 Isolate 的使用对于开发高性能的 Dart 应用很有帮助。