尝试使用 Isolate.spawn() 时出现类型转换错误
Type conversion error when trying to use Isolate.spawn()
我在使用 Isolate.spawn() 时遇到 Dart 泛型类型的问题。我觉得这应该行,但行不通。
我正在尝试围绕 Isolate.spawn() 编写一个类型安全的(-ish)包装器,这将确保我将有效类型传递到我想要的函数中 运行在另一个线程(输入参数)中,以及我从该函数获得的结果值的类型(输出结果值)。
因此,我创建了 InputType
和 OutputType
虚拟 类 作为我的输入和输出类型。 thread
函数是我想在另一个线程中 运行 的函数。 run
函数是实际的包装器:它应该接受另一个线程中 运行 的函数,它是参数。
import 'dart:async';
import 'dart:isolate';
typedef Callback<I, R> = Future<R> Function(I input);
class Config<I, R> {
final Callback<I, R> callback;
final I arg;
final SendPort port;
Config(this.callback, this.arg, this.port);
}
class InputType {
int arg;
InputType(this.arg);
}
class OutputType {
String str;
OutputType(this.str);
}
Future<R> _spawn<I, R>(Config<I, R> conf) async {
print("callback: ${conf.callback}");
return await conf.callback(conf.arg);
}
void run<I, R>(Callback<I, R> func, I arg) async {
ReceivePort resultPort = ReceivePort();
Config<I, R> conf = Config<I, R>(func, arg, resultPort.sendPort);
Isolate thread = await Isolate.spawn<Config<I, R>>(_spawn, conf);
// ...
}
Future<OutputType> thread(InputType input) async {
print("running in isolate");
return OutputType("Hello, arg was: ${input.arg}");
}
void main() async {
print("runtime");
run<InputType, OutputType>(thread, InputType(123));
}
我遇到的结果错误:
$ dart isolate.dart
runtime
Unhandled exception:
type '(InputType) => Future<OutputType>' is not a subtype of type '(dynamic) => Future<dynamic>'
#0 _spawn (file:///home/antek/dev/dart/tests/generic/isolate.dart:24:27)
#1 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:286:17)
#2 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
^C
错误实际上来自这一行:
print("callback: ${conf.callback}");
有人知道如何解决这个问题吗?
Dart hackity-hack 助您一臂之力。
似乎在将对 _spawn
函数的引用传递给 Isolate.spawn()
时,类型信息丢失了。
我发现的一个修复方法是在 Config<I, R>
class 中添加一个调用回调的辅助函数。 Config<I, R>
的实例似乎包含有关类型的所有必要信息。所以,在我像这样修改上面的示例之后:
class Config<I, R> {
final Callback<I, R> callback;
final I arg;
final SendPort port;
Config(this.callback, this.arg, this.port);
Future<R> call() async {
return await callback(arg);
}
}
// ...
Future<R> _spawn<I, R>(Config<I, R> conf) async {
var result = await conf.call();
return result;
}
它开始正常工作。
具有必要的阻塞和单向通信的完整示例源:
import 'dart:async';
import 'dart:isolate';
typedef Callback<I, R> = Future<R> Function(I input);
class Config<I, R> {
final Callback<I, R> callback;
final I arg;
final SendPort port;
Config(this.callback, this.arg, this.port);
Future<R> call() async {
return await callback(arg);
}
}
class InputType {
int arg;
InputType(this.arg);
}
class OutputType {
String str;
OutputType(this.str);
}
Future<R> _spawn<I, R>(Config<I, R> conf) async {
var result = await conf.call();
conf.port.send(result);
return result;
}
Future<R> run<I, R>(Callback<I, R> func, I arg) async {
ReceivePort resultPort = ReceivePort();
Config<I, R> conf = Config<I, R>(func, arg, resultPort.sendPort);
Future<Isolate> thread = Isolate.spawn<Config<I, R>>(_spawn, conf);
var c = Completer<R>();
resultPort.listen((data) {
c.complete(data as R);
});
await c.future;
resultPort.close();
(await thread).kill();
return c.future;
}
Future<OutputType> thread(InputType input) async {
return OutputType("Hello, arg was: ${input.arg}");
}
void main() async {
var result = await run<InputType, OutputType>(thread, InputType(123));
print("main() result: ${result.str}");
}
我在使用 Isolate.spawn() 时遇到 Dart 泛型类型的问题。我觉得这应该行,但行不通。
我正在尝试围绕 Isolate.spawn() 编写一个类型安全的(-ish)包装器,这将确保我将有效类型传递到我想要的函数中 运行在另一个线程(输入参数)中,以及我从该函数获得的结果值的类型(输出结果值)。
因此,我创建了 InputType
和 OutputType
虚拟 类 作为我的输入和输出类型。 thread
函数是我想在另一个线程中 运行 的函数。 run
函数是实际的包装器:它应该接受另一个线程中 运行 的函数,它是参数。
import 'dart:async';
import 'dart:isolate';
typedef Callback<I, R> = Future<R> Function(I input);
class Config<I, R> {
final Callback<I, R> callback;
final I arg;
final SendPort port;
Config(this.callback, this.arg, this.port);
}
class InputType {
int arg;
InputType(this.arg);
}
class OutputType {
String str;
OutputType(this.str);
}
Future<R> _spawn<I, R>(Config<I, R> conf) async {
print("callback: ${conf.callback}");
return await conf.callback(conf.arg);
}
void run<I, R>(Callback<I, R> func, I arg) async {
ReceivePort resultPort = ReceivePort();
Config<I, R> conf = Config<I, R>(func, arg, resultPort.sendPort);
Isolate thread = await Isolate.spawn<Config<I, R>>(_spawn, conf);
// ...
}
Future<OutputType> thread(InputType input) async {
print("running in isolate");
return OutputType("Hello, arg was: ${input.arg}");
}
void main() async {
print("runtime");
run<InputType, OutputType>(thread, InputType(123));
}
我遇到的结果错误:
$ dart isolate.dart
runtime
Unhandled exception:
type '(InputType) => Future<OutputType>' is not a subtype of type '(dynamic) => Future<dynamic>'
#0 _spawn (file:///home/antek/dev/dart/tests/generic/isolate.dart:24:27)
#1 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:286:17)
#2 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
^C
错误实际上来自这一行:
print("callback: ${conf.callback}");
有人知道如何解决这个问题吗?
Dart hackity-hack 助您一臂之力。
似乎在将对 _spawn
函数的引用传递给 Isolate.spawn()
时,类型信息丢失了。
我发现的一个修复方法是在 Config<I, R>
class 中添加一个调用回调的辅助函数。 Config<I, R>
的实例似乎包含有关类型的所有必要信息。所以,在我像这样修改上面的示例之后:
class Config<I, R> {
final Callback<I, R> callback;
final I arg;
final SendPort port;
Config(this.callback, this.arg, this.port);
Future<R> call() async {
return await callback(arg);
}
}
// ...
Future<R> _spawn<I, R>(Config<I, R> conf) async {
var result = await conf.call();
return result;
}
它开始正常工作。
具有必要的阻塞和单向通信的完整示例源:
import 'dart:async';
import 'dart:isolate';
typedef Callback<I, R> = Future<R> Function(I input);
class Config<I, R> {
final Callback<I, R> callback;
final I arg;
final SendPort port;
Config(this.callback, this.arg, this.port);
Future<R> call() async {
return await callback(arg);
}
}
class InputType {
int arg;
InputType(this.arg);
}
class OutputType {
String str;
OutputType(this.str);
}
Future<R> _spawn<I, R>(Config<I, R> conf) async {
var result = await conf.call();
conf.port.send(result);
return result;
}
Future<R> run<I, R>(Callback<I, R> func, I arg) async {
ReceivePort resultPort = ReceivePort();
Config<I, R> conf = Config<I, R>(func, arg, resultPort.sendPort);
Future<Isolate> thread = Isolate.spawn<Config<I, R>>(_spawn, conf);
var c = Completer<R>();
resultPort.listen((data) {
c.complete(data as R);
});
await c.future;
resultPort.close();
(await thread).kill();
return c.future;
}
Future<OutputType> thread(InputType input) async {
return OutputType("Hello, arg was: ${input.arg}");
}
void main() async {
var result = await run<InputType, OutputType>(thread, InputType(123));
print("main() result: ${result.str}");
}