首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >尝试使用Isolate.spawn()时出现类型转换错误

尝试使用Isolate.spawn()时出现类型转换错误
EN

Stack Overflow用户
提问于 2021-11-22 06:25:05
回答 1查看 43关注 0票数 0

在使用Isolate.spawn()时,我遇到了Dart泛型类型的问题。我觉得这应该行得通,但是不行。

我正在尝试编写一个围绕Isolate.spawn()的类型安全(-ish)包装器,它将确保我将有效类型传递给我想在另一个线程中运行的函数(输入参数),以及我从该函数获得的结果值的类型(输出结果值)。

因此,我创建了InputTypeOutputType虚拟类作为我的输入和输出类型。thread函数是我希望在另一个线程中运行的函数。run函数是实际的包装器:它应该接受该函数在另一个线程中运行,它的参数。

代码语言:javascript
复制
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));
}

我得到的resultig错误是:

代码语言:javascript
复制
$ 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

错误实际上来自这一行:

代码语言:javascript
复制
print("callback: ${conf.callback}");

有谁知道如何解决这个问题吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-11-22 11:10:51

Dart hackity--hack来拯救你。

似乎在将对_spawn函数的引用传递给Isolate.spawn()时,类型信息正在丢失。

我发现的一个修复方法是在调用回调的Config<I, R>类中添加一个帮助器函数。Config<I, R>的实例似乎包含有关类型的所有必要信息。所以,在我像这样修改了上面的例子之后:

代码语言:javascript
复制
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;
}

它开始正常工作。

具有必要的阻塞和单向通信的完整示例源代码:

代码语言:javascript
复制
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}");
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70061648

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档