diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.OutOfProcess/WorkerPipeSecurity.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.OutOfProcess/WorkerPipeSecurity.cs
index 5c491e7ab..07cc6c394 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.OutOfProcess/WorkerPipeSecurity.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.OutOfProcess/WorkerPipeSecurity.cs
@@ -50,11 +50,20 @@ internal static class WorkerPipeSecurity
return security;
}
+ ///
+ /// The pipe's buffer quota in each direction (lmxopcua#789). With a quota of 0 an overlapped write stays pending
+ /// until the peer has READ the bytes, so a blocking writer ()
+ /// would wait out a full peer wake-up per frame — measured on windev as half the closed-loop throughput. With a
+ /// quota a write completes as soon as the bytes are buffered; a peer that stops reading still fills it and blocks
+ /// the writer, which the heartbeat monitor ends.
+ ///
+ internal const int BufferBytes = 1024 * 1024;
+
/// Creates the single-instance server end of a worker pipe with .
/// The random pipe name.
/// The ACL ().
/// The server stream.
public static NamedPipeServerStream CreateServer(string pipeName, PipeSecurity security)
=> NamedPipeServerStreamAcl.Create(pipeName, PipeDirection.InOut, maxNumberOfServerInstances: 1,
- PipeTransmissionMode.Byte, PipeOptions.Asynchronous, inBufferSize: 0, outBufferSize: 0, security);
+ PipeTransmissionMode.Byte, PipeOptions.Asynchronous, inBufferSize: BufferBytes, outBufferSize: BufferBytes, security);
}