From d49eca0ae3687f84fe20aed2c95d1b157145bbbe Mon Sep 17 00:00:00 2001 From: Martin Regen Date: Mon, 7 Nov 2016 11:28:27 +0100 Subject: [PATCH] fix threading issues in console publisher --- .../NetCoreConsolePublisher/AmqpConnection.cs | 61 +++++- .../Opc.Ua.Publisher.Endpoints.xml | 18 +- .../Opc.Ua.Publisher.config.xml | 8 +- .../NetCoreConsolePublisher/Program.cs | 188 ++++++++++-------- 4 files changed, 162 insertions(+), 113 deletions(-) diff --git a/SampleApplications/Samples/NetCoreConsolePublisher/AmqpConnection.cs b/SampleApplications/Samples/NetCoreConsolePublisher/AmqpConnection.cs index a3edd4e6f1..f7923b88ba 100644 --- a/SampleApplications/Samples/NetCoreConsolePublisher/AmqpConnection.cs +++ b/SampleApplications/Samples/NetCoreConsolePublisher/AmqpConnection.cs @@ -75,12 +75,14 @@ namespace Opc.Ua.Publisher private Connection m_connection; private Session m_session; private SenderLink m_link; - private Queue> messages; + private LinkedList> messages; private DateTime m_currentExpiryTime; private Timer m_tokenRenewalTimer; private bool m_closed; private int m_counter; + private object m_sending; + private int m_sendallthreads; #endregion @@ -108,7 +110,13 @@ namespace Opc.Ua.Publisher /// private void Initialize() { - messages = new Queue>(); + m_connection = null; + m_session = null; + m_link = null; + m_closed = true; + m_sending = new object(); + m_sendallthreads = 0; + messages = new LinkedList>(); } #endregion @@ -156,7 +164,7 @@ namespace Opc.Ua.Publisher { lock (messages) { - messages.Enqueue(body); + messages.AddLast(body); } if (IsClosed()) @@ -175,16 +183,40 @@ namespace Opc.Ua.Publisher /// protected void SendAll() { + // make sure only one send all task is active + if (Interlocked.Increment(ref m_sendallthreads) != 1) + { + Interlocked.Decrement(ref m_sendallthreads); + return; + } + try { - lock (messages) + + while (!IsClosed()) { - while (!IsClosed() && messages.Count != 0) + ArraySegment onemessage; + lock (messages) { - bool sent = SendOne(messages.Peek()); - if (sent) + if (messages.Count == 0) { - messages.Dequeue(); + break; + } + onemessage = messages.First.Value; + messages.RemoveFirst(); + } + + bool sent; + lock (m_sending) + { + sent = SendOne(onemessage); + } + + if (!sent) + { + lock (messages) + { + messages.AddFirst(onemessage); } } } @@ -193,6 +225,10 @@ namespace Opc.Ua.Publisher { Close(); } + finally + { + Interlocked.Decrement(ref m_sendallthreads); + } } /// @@ -360,7 +396,10 @@ namespace Opc.Ua.Publisher } // Ensure we have a token - await RenewTokenAsync(GenerateSharedAccessToken()); + lock (m_sending) + { + RenewTokenAsync(GenerateSharedAccessToken()).Wait(); + } // then start the periodic renewal int interval = (int)(TokenLifetime * 0.8); @@ -442,12 +481,12 @@ namespace Opc.Ua.Publisher { try { - lock (messages) + lock (m_sending) { bool result = RenewTokenAsync(GenerateSharedAccessToken()).Wait(60000); if (!result) { - Utils.Trace( "Unexpected timeout error renewing token."); + Utils.Trace("Unexpected timeout error renewing token."); } } } diff --git a/SampleApplications/Samples/NetCoreConsolePublisher/Opc.Ua.Publisher.Endpoints.xml b/SampleApplications/Samples/NetCoreConsolePublisher/Opc.Ua.Publisher.Endpoints.xml index a828504cf2..a73d2d3093 100644 --- a/SampleApplications/Samples/NetCoreConsolePublisher/Opc.Ua.Publisher.Endpoints.xml +++ b/SampleApplications/Samples/NetCoreConsolePublisher/Opc.Ua.Publisher.Endpoints.xml @@ -7,23 +7,7 @@ - opc.tcp://localhost:61210/UA/SampleClient - SignAndEncrypt_3 - http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15 - - - Anonymous_0 - - - http://opcfoundation.org/UA/profiles/transport/wsxmlorbinary - 0 - - true - 0 - - - - opc.tcp://192.168.2.101:51210/UA/SampleServer + opc.tcp://localhost:61410/UA/SampleClient SignAndEncrypt_3 http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15 diff --git a/SampleApplications/Samples/NetCoreConsolePublisher/Opc.Ua.Publisher.config.xml b/SampleApplications/Samples/NetCoreConsolePublisher/Opc.Ua.Publisher.config.xml index 586cead167..06724f0c7e 100644 --- a/SampleApplications/Samples/NetCoreConsolePublisher/Opc.Ua.Publisher.config.xml +++ b/SampleApplications/Samples/NetCoreConsolePublisher/Opc.Ua.Publisher.config.xml @@ -91,6 +91,10 @@ OPC Foundation/CertificateStores/RejectedCertificates + + true + @@ -143,8 +147,8 @@ For example, a URL used for an endpoint which uses the Basic256 security policy would look like this: http://localhost:61211/UA/SampleClient/Basic256 --> - opc.tcp://localhost:61210/UA/SampleClient - https://localhost:61212/UA/SampleClient/ + opc.tcp://localhost:61410/UA/SampleClient + https://localhost:61412/UA/SampleClient/