跳到主要内容

主动异步隔离 (Async Isolation)

本页是"主动异步隔离层"的参考。 它把 build / setState / SDO 读写 / 静态扫描这些会阻塞总线/邮箱的同步操作,包装成"提交即返回 CompletableFuture、后台串行执行、可取消、带进度"的异步版本,避免在 Swing / JavaFX / 服务线程上卡死,并保证同一主站任意时刻只有一个操作打总线

语义对齐 C# —— 实现与 C# 主动异步隔离 逐点一致:每主站串行闸(单线程 ExecutorService,等价 SemaphoreSlim(1,1))、关闭守门、取消后自动恢复干净状态、独立静态扫描闸。命名遵循 Java 惯例(...Async 后缀 + CompletableFuture)。旧同步 API 全部保留。

FFI 与命名空间

异步隔离层位于包 com.darra.ethercat.masterAsyncGate)与 com.darra.ethercat.slaveCoE),经 JNA 调用底层运行时库。AsyncGate.runExclusiveAsync(name, supplier) 为核心串行闸。

一、设计要点

要点实现
串行 (Serial)每主站一把 AsyncGate = 单线程 daemon ExecutorService(FIFO,等价 SemaphoreSlim(1,1))。同一主站的 build / setState / SDO 严格串行,绝不并发打总线/邮箱。SDO 经 AsyncGate.forMaster(index) 反查父闸排队。
后台隔离 (Isolation)...Async 提交即返回 CompletableFuture,阻塞 native 在后台线程执行,不堵调用线程。
守门 (Shutdown Guard)volatile shuttingDown;提交前 + 进 native 前各查一次。close() asyncGate.shutdown() dll.Dispose(顺序正确),防 use-after-free。
取消 (Cancel)对返回的 CompletableFuturecancel(true)whenComplete 中断正在执行的 native 阻塞调用并自动恢复到可继续接受新操作的干净状态,不影响后续操作。静态扫描的取消走独立通道,与主站取消互不干扰。
进度 (Progress)Consumer<String> 回调 + InitProgressListener回调在 executor 后台线程触发,调用方需自己 marshal 回 UI。
进度回调在后台线程 — 必须自己 marshal

所有进度回调都在 executor 后台线程 触发,不是 EDT / JavaFX Application Thread。Swing 用 SwingUtilities.invokeLater、JavaFX 用 Platform.runLater,否则跨线程访问 UI 控件会出问题。

master.buildAsync(msg ->
// ✅ marshal 回 EDT
SwingUtilities.invokeLater(() -> statusLabel.setText(msg))
);

二、API 总览

类别方法返回类型读写说明
主站一条龙buildAsync(Consumer<String> progress)CompletableFuture<Boolean>异步异步执行 连接→扫描→配置→进 OP,带进度
主站一条龙buildAsync()CompletableFuture<Boolean>异步无进度回调的构建
状态切换setStateAsync(EcState)CompletableFuture<Boolean>异步异步状态切换,经串行闸排队
状态切换setStateAsync(EcState, Consumer<String>)CompletableFuture<Boolean>异步带进度的异步状态切换
网络setNetworkAsync(String, String)CompletableFuture<Integer>异步异步设主/冗余网卡(链式串行用)
静态扫描scanAsync(String adapter, String secondary)CompletableFuture<List<...>>异步异步静态扫描,走独立扫描闸 + 独立取消通道
静态扫描scanAsync(String adapter)CompletableFuture<List<...>>异步单网卡静态扫描
从站 SDOCoE.sdoReadAsync(...)CompletableFuture<byte[]>异步异步读 SDO(抛 CoEAbortException 风格)
从站 SDOCoE.sdoWriteAsync(...)CompletableFuture<Void>异步异步写 SDO
从站 SDOCoE.SDOReadAsync(...)CompletableFuture<byte[]>异步C# 风格:失败返回 null
从站 SDOCoE.SDOWriteAsync(...)CompletableFuture<Boolean>异步C# 风格:失败返回 false
串行闸AsyncGate.runExclusiveAsync(String, Supplier<T>)CompletableFuture<T>异步核心串行闸,自定义异步操作入闸
静态闸AsyncGate.runStaticExclusiveAsync(...)CompletableFuture<T>异步进程级独立静态扫描闸
进度setInitProgressListener(InitProgressListener)void注册初始化进度多播监听器(后台线程触发)
状态查询isAsyncOperationInProgress()boolean只读当前是否有异步操作在串行闸中执行

三、方法详解

buildAsync(Consumer<String> progress)

public CompletableFuture<Boolean> buildAsync(Consumer<String> progress)
public CompletableFuture<Boolean> buildAsync()

异步执行"连接 → 扫描 → 配置 → 进 OP"一条龙。提交即返回 CompletableFuture,构建在 executor 后台线程串行执行。

参数:

  • progress (Consumer<String>) — 进度回调,在后台线程触发,调用方自行 marshal 回 UI

返回值:

  • CompletableFuture<Boolean> — 完成时为 true 构建成功并进入 OP

示例:

CompletableFuture<Boolean> f = master.buildAsync(msg ->
SwingUtilities.invokeLater(() -> statusLabel.setText(msg)));
f.thenAccept(ok -> {
if (!ok) System.out.println("构建失败");
});

setStateAsync(EcState state)

public CompletableFuture<Boolean> setStateAsync(EcState state)
public CompletableFuture<Boolean> setStateAsync(EcState state, Consumer<String> progress)

异步状态切换,经主站串行闸排队,与同主站的 build / SDO 互斥串行。

示例:

master.setStateAsync(EcState.OP).thenAccept(ok -> { /* ... */ });

CoE.sdoReadAsync / sdoWriteAsync

public CompletableFuture<byte[]> sdoReadAsync(int index, int subIndex, boolean completeAccess)
public CompletableFuture<Void> sdoWriteAsync(int index, int subIndex, byte[] data, boolean completeAccess)
// C# 风格重载(失败返回 null / false 而非抛异常)
public CompletableFuture<byte[]> SDOReadAsync(int index, int subIndex, boolean completeAccess)
public CompletableFuture<Boolean> SDOWriteAsync(int index, int subIndex, byte[] data, boolean completeAccess)

异步 SDO 读写。经 AsyncGate.forMaster(masterIndex) 反查父主站的同一把串行闸排队,绝不与同主站 PDO / 状态切换并发打邮箱。

示例:

master.slave(1).getCoE().sdoReadAsync(0x6041, 0x00, false)
.thenAccept(data -> System.out.println("读到 " + data.length + " 字节"));

scanAsync(String adapter, String secondaryAdapter)

public CompletableFuture<List<ScannedSlaveInfo>> scanAsync(String adapter, String secondaryAdapter)
public CompletableFuture<List<ScannedSlaveInfo>> scanAsync(String adapter)

异步静态扫描。走进程级独立扫描闸,取消时通过独立的扫描取消通道中断(与主站操作的取消严格区分,互不干扰)。

setInitProgressListener(InitProgressListener)

public void setInitProgressListener(InitProgressListener listener)

注册初始化进度多播监听器。回调在后台线程触发,Swing / JavaFX 需自行 marshal。

四、取消语义

对返回的 CompletableFuturecancel(true),隔离层会中断正在执行的 native 阻塞调用,并在中断后自动把隔离层恢复到可继续接受新操作的干净状态:

操作类型取消行为
主站 build / setState / SDO中断当前主站操作,自动清理中断状态
静态扫描 scanAsync独立取消通道中断扫描,与主站取消互不干扰
取消后可直接继续

取消由隔离层完整托管:中断后会自动恢复,后续 build / setState 不会被前一次取消影响,应用层无需任何额外清理动作。

CompletableFuture<Boolean> f = master.buildAsync(null);
cancelButton.addActionListener(e -> f.cancel(true)); // 取消并自动清理

兼容性

异步隔离层以 AsyncGatemaster 包)、CoEslave 包)和 MasterAsyncsugar 包)三组公开类型对外暴露,经 JNA 调用底层运行时库。原同步 build / setState / setNetwork / SDORead / SDOWrite 全部保留,向后兼容。