Phi*_*ste 5 dart dart-isolates dart-ffi
我正在致力于为 Dart 公开一个音频库(C 库)。要触发音频引擎,需要一些初始化步骤(对于 UI 来说是非阻塞的),然后使用执行函数触发音频处理,该函数是阻塞的(音频处理是一项繁重的任务)。这就是我开始阅读有关 Dart 分离株的原因。
我的第一个想法是我只需要调用isolate中的性能方法,但这似乎不可能,因为perform函数将引擎状态作为第一个参数 - 这个引擎状态是一个不透明的指针(dart中的指针:ffi )。当尝试使用计算函数将引擎状态传递给新的隔离时,Dart VM 返回错误 - 它无法将 C 指针传递给隔离。
我找不到一种方法将此数据传递给隔离区,我认为这是由于主隔离区和我正在创建的隔离区的内存不同所致。
因此,我可能应该在隔离中管理整个引擎状态,这意味着:
我找不到任何有关如何在隔离中执行此操作的示例,而是从主线程/隔离触发。也没有讨论如何管理隔离内存(保持引擎状态并使用它)。我当然可以
这是我想要做的一个非孤立的例子:
Pointer<Void> engineState = createEngineState();
initEngine(engineState, parametersString);
startEngine(engineState);
perform(engineState);
Run Code Online (Sandbox Code Playgroud)
在运行时,由 UI 操作触发(例如滑块值更改或单击按钮):
setEngineControl(engineState, valueToSet);
double controleValue = getEngineControl(engineState);
Run Code Online (Sandbox Code Playgroud)
引擎状态可以封装在一个类中,我认为这在这里并不重要。无论是类还是不透明的数据类型,我都找不到如何管理和保持这种状态,并从主线程执行触发器(在隔离中处理)。任何想法 ?
提前谢谢。
PS:我注意到,在写作时,我的问题/解释可能不准确,我不得不说我在这里有点迷失,因为我从未使用过 Dart Isolates。如果缺少某些信息,请告诉我。
4 月 24 日编辑:它似乎正在创建和管理 Isolate 内的对象状态。但主要问题还没有解决。因为执行方法在未完成时实际上是阻塞的,所以无法在隔离中仍然接收消息。我首先想到的一个选项是使用 PerformBlock 方法,该方法仅执行音频样本块。像这样 :
while(performBlock(engineState)) {
// listen messages, and do something
}
Run Code Online (Sandbox Code Playgroud)
但这似乎不起作用,进程仍然被阻塞,直到音频表演结束。即使在隔离中的异步方法中调用此循环,它也会阻塞,并且不会读取任何消息。
我现在考虑将Pointer<Void>主隔离中的托管传递给另一个的可能性,这将是工作人员(仅适用于执行方法),然后能够从主隔离中触发一些控制方法。
isolate Dart包提供了一个注册表子库来管理一些共享内存。但在isolates之间传递void指针仍然是不可能的。
[错误:flutter/lib/ui/ui_dart_state.cc(157)] 未处理的异常:无效参数:本机对象(来自 dart:ffi),例如指针和结构不能在隔离之间传递。
有人遇到过这种情况吗?
小智 6
可以获取 thisPointer指向的数字地址并Pointer从该地址构造一个新地址(请参阅Pointer.address和Pointer.fromAddress())。由于数字可以在隔离之间自由传递,因此可以使用它在隔离之间传递本机指针。
在你的情况下,可以这样做,例如,像这样(我使用 Flutter 的计算来使示例更简单,但这显然也可以与显式使用Send/ReceivePorts 一起使用)
// Callback to be used in a backround isolate.
// Returns address of the new engine.
int initEngine(String parameters) {
Pointer<Void> engineState = createEngineState();
initEngine(engineState, parameters);
startEngine(engineState);
return engineState.address;
}
// Callback to be used in a backround isolate.
// Does whichever processing is needed using the given engine.
void processWithEngine(int engineStateAddress) {
final engineState = Pointer<Void>.fromAddress(engineStateAddress);
process(engineState);
}
void main() {
// Initialize the engine in a background isolate.
final address = compute(initEngine, "parameters");
final engineState = Pointer<Void>.fromAddress(address);
// Do some heavy computation in a background isolate using the engine.
compute(processWithEngine, engineState.address);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2642 次 |
| 最近记录: |