- Posts: 11
- Thank you received: 0
Online Forums
Technical support is provided through Support Forums below. Anybody can view them; you need to Register/Login to our site (see links in upper right corner) in order to Post questions. You do not have to be a licensed user of our product.
Please read Rules for forum posts before reporting your issue or asking a question. OPC Labs team is actively monitoring the forums, and replies as soon as possible. Various technical information can also be found in our Knowledge Base. For your convenience, we have also assembled a Frequently Asked Questions page.
Do not use the Contact page for technical issues.
- Forum
- Discussions
- QuickOPC-Classic in .NET
- Connections, Reconnections, COM/DCOM
- Random Disconnect from OPC server
Random Disconnect from OPC server
Thank you very much for your support. We will try the proposed solution.
Please Log in or Create an account to join the conversation.
I tried to reproduce the issue again. I still was not able to reproduce the "inability to reconnect" after > 10 minutes. But, on the other hand, I was able to get "Read not completed..." errors, if I continued increasing the number of threads, even during normal operation.So, I went to analyze what is happening, and here is the outcome:
As the number of threads increases, two aspect of the load on the component increase:
1. The "basic" and obvious increase is in the fact that total number of reads per unit of time increases. So, more needs to be processed on the client, through the network, and on the server. The consequence is that the time to complete ReadMultipleItems may increase as well.
2. When the reads and invoked by separate threads on separate EasyDAClient instances, the component sees them as one incoming stream of item read requests, and may do sub-optimal job in putting requests together to achieve highest performance (in OPC, it is desirable to "group" multiple requests into a single operation, if possible). Precisely explaining this would require long discussion of the internal implementation details of EasyDAClient, so for now it should suffice that there a recommendation to overcome this - see further below.
It is possible that the problem with the reconnection is just an odd manifestation of the same thing. So, I went to modify your test program to see if I can make it work better. It seems counter-intuitive, but it is actually better to use just one common EasyDAClient instance (at least for the Read operations). Doing so eliminates the possible performance degradation described in #2 above. My resulting code looks like this:
namespace OpcLabsTest
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using OpcLabs.EasyOpc;
using OpcLabs.EasyOpc.DataAccess;
using OpcLabs.EasyOpc.DataAccess.OperationModel;
public class Program
{
static public void Main(string[] args)
{
EasyDAClient.SharedParameters.TopicParameters.SlowdownWeight = 0.0f;
EasyDAClient.SharedParameters.TopicParameters.SpeedupWeight = 0.0f;
OpcClient.InstanceParameters.Mode.AllowAsynchronousMethod = false;
OpcClient.InstanceParameters.UpdateRates.ReadAutomatic = Timeout.Infinite;
OpcClient.InstanceParameters.UpdateRates.WriteAutomatic = Timeout.Infinite;
Subscribe();
for (int i = 0; i < 500; ++i)
{
Task.Run(() => PullingCollectorThread(i));
Thread.Sleep(500);
}
Console.WriteLine("Test started");
Console.ReadKey();
}
static private void PullingCollectorThread(int id)
{
while (true)
{
var cache = new List<DAVtqResult>();
DAVtqResult[] results = OpcClient.ReadMultipleItems(new[]
{
GetDATagArguments("WTG10.Int1"),
GetDATagArguments("WTG10.Alm"),
GetDATagArguments("WTG10.Bool"),
GetDATagArguments("WTG10.Int2"),
GetDATagArguments("WTG10.Int4"),
GetDATagArguments("WTG10.String1"),
GetDATagArguments("WTG10.Time"),
GetDATagArguments("WTG10.Time1"),
GetDATagArguments("WTG1.Alm"),
GetDATagArguments("WTG1.Bool"),
GetDATagArguments("WTG1.Int1"),
GetDATagArguments("WTG1.Int2"),
GetDATagArguments("WTG1.Int4"),
GetDATagArguments("WTG1.String1"),
GetDATagArguments("WTG1.Time"),
GetDATagArguments("WTG1.Time1"),
});
if (results.First().Succeeded)
{
Console.WriteLine($"Test #{id} WTG10.Int1: {results[0].Vtq.Value}({results[0].Vtq.Quality})");
}
else
{
Console.WriteLine($"Test #{id} Error happened: {results[0].Exception.Message}");
}
cache.Add(results[0]);
Thread.Sleep(2000);
}
}
static private void Subscribe()
{
var opcClient = new EasyDAClient();
opcClient.ItemChanged += OnSubscriptionDataChanged;
const string itemId = "WTG10.Int1";
opcClient.SubscribeMultipleItems(
new[] {
new EasyDAItemSubscriptionArguments(
new DAItemGroupArguments(
ServerDescriptor,
new DAItemDescriptor(itemId),
new DAGroupParameters(requestedUpdateRate:2 * 1000, percentDeadband: 0),
state:itemId)
)});
}
static private void OnSubscriptionDataChanged(object state, EasyDAItemChangedEventArgs args)
{
Console.WriteLine(args);
}
static private DAReadItemArguments GetDATagArguments(string tag)
{
return new DAReadItemArguments(ServerDescriptor, tag);
}
static private readonly EasyDAClient OpcClient = new EasyDAClient();
static private readonly ServerDescriptor ServerDescriptor = "opcda://10.1.0.6/Matrikon.OPC.Simulation.1";
}
}
I therefore suggest that you "copy back" the principles of the code above to your production program - main things to watch out for are:
a) The settings made to static and instance properties of the EasyDAClient at the beginning of the Main() functions, and
b) The usage of common EasyDAClient instance for the reads.
Regards
Please Log in or Create an account to join the conversation.
1) The number of threads using EasyDAClient in our main application is dynamic (depends on some configurations). But normally it should not be more than a hundred.
2) In the test application, it was a Debug configuration that targets an AnyCPU running under 32-bit process. In the main application, we are going to target x64 platforms.
3) I observed it when running without the debugger.
4) It is still "Read not completed ..."
Please Log in or Create an account to join the conversation.
I could not reproduce it so far - not even after waiting over 10 minutes.
Can you please answer some additional questions:
1. How many items and threads (I mean threads that use EasyDAClient) are there in the real program? I understand that in the sample code, it is artificially high, for the purpose of achieving the repro - but obviously there are always limits as to how far one can go.
2. In the main project properties, are you targeting x86, x64, or AnyCPU? If AnyCPU, are you running it under 32-bit or 64-bit process?
3. Do you observe the issue when running with the debugger, without the debugger, or in both cases?
4. With the newest build of QuickOPC, are you still getting "Read not completed..."? If not, what are the symptoms (e.g. other error, or does it block forever in the ReadMultipleItems, etc.
Thank you
Please Log in or Create an account to join the conversation.
Is there any news on this one?
Please Log in or Create an account to join the conversation.
It is really important to us to make this work since some of our customers have poor network quality between our system and OPC server and we need to be sure that this will not result in some significant data loss.
It would be also helpful if you can advise us in which direction should we dig to find the cause. Can it be some system resources, network or COM configuration ... anything we can help with?
Please Log in or Create an account to join the conversation.
I was not able to reproduce the issue, when using your code as it was, or with the first set of parameters.
The second set of parameters you have tried (with Isolated = true) indeed brings problems, although in my case I was able to get the data sometimes. But in this case, it in understandable. What happens is that if, as in this program, you have 501 EasyDAClient objects, with Isolated = false they all share one connection to the target OPC server, but with Isolated = true there are 501 connections to the servers, creating a very high load on the client, the network, and the server. There should be no need to "isolate" the connections in this way. The setting is meant a) for special where you truly need two connections to the same server, and b) for creating some libraries which want to be sure they are not influenced by possibly other things going on in the same process and using QuickOPC. In this case (b), however, you would create one EasyDAClient instance, set its Isolated to 'true', and use it at multiple places in the program - and not create the EasyDAClient instance inside each thread or routine.
Note that I have done the tests with recent build of QuickOPC 2018.3 (i.e. 5.54.1115.1).This build already has a fix for the other reported problem. The nature of the problem was either error messages about improper server response could have been issued, OR data updates from the server could have been "thrown away" - under rare circumstances, but quite unpredictable (it depended on memory allocation layout). So, in any case, please repeat your test with this recent build. Other than that, without having a reproducible case, I cannot proceed any further at the moment, sorry.
Regards
Please Log in or Create an account to join the conversation.
Please Log in or Create an account to join the conversation.
There are no Mode and UpdateRates properties in EasyDAClient.AdaptableParameters.
We have tried :
EasyDAClient.SharedParameters.TopicParameters.SlowdownWeight = 0.0f;
EasyDAClient.SharedParameters.TopicParameters.SpeedupWeight = 0.0f;
EasyDAClient.SharedInstance.InstanceParameters.Mode.AllowAsynchronousMethod = false;
EasyDAClient.SharedInstance.InstanceParameters.UpdateRates.ReadAutomatic = Timeout.Infinite;
EasyDAClient.SharedInstance.InstanceParameters.UpdateRates.WriteAutomatic = Timeout.Infinite;
with "Isolated" set to false. No changes in behavior. Still fails.
We also have tried:
EasyDAClient.SharedParameters.TopicParameters.SlowdownWeight = 0.0f;
EasyDAClient.SharedParameters.TopicParameters.SpeedupWeight = 0.0f;
EasyDAClient opcClient = new EasyDAClient();
opcClient.Isolated = true;
opcClient.InstanceParameters.Mode.AllowAsynchronousMethod = false;
opcClient.InstanceParameters.UpdateRates.ReadAutomatic = Timeout.Infinite;
opcClient.InstanceParameters.UpdateRates.WriteAutomatic = Timeout.Infinite;
In the second case, it infinitely hangs without reconnection.
Please Log in or Create an account to join the conversation.
I will try to reproduce it on our side. However, due to business trip duties I cannot start on it sooner than in the end of the next week.
In the meantime, I'd like to ask you to try one more thing - Enhance your code similarly to this:
EasyDAClient.SharedParameters.TopicParameters.SlowdownWeight = 0.0f;
EasyDAClient.SharedParameters.TopicParameters.SpeedupWeight = 0.0f;
EasyDAClient.AdaptableParameters.Mode.AllowAsynchronousMethod = false;
EasyDAClient.AdaptableParameters.UpdateRates.ReadAutomatic = Timeout.Infinite;
EasyDAClient.AdaptableParameters.UpdateRates.WriteAutomatic = Timeout.Infinite;
The code would be slightly different if you are setting the Isolated property to 'true'; in that case, the last 3 parameters need to be set in the InstanceParameters of the EasyDAClient instance.
The settings are designed to switch off some parts of the internal logic that we have seen in the past to possibly cause problems.
Regards
Please Log in or Create an account to join the conversation.
- Forum
- Discussions
- QuickOPC-Classic in .NET
- Connections, Reconnections, COM/DCOM
- Random Disconnect from OPC server