Closed maxxie85 closed 11 months ago
This doesn't happen when using 6.0.194 so this appears to be a regression in the latest version.
Actually, I am not able to reproduce the issue. With the following code
using TwinCAT;
using TwinCAT.Ads;
using TwinCAT.Ads.Reactive;
using TwinCAT.Ads.TypeSystem;
using TwinCAT.TypeSystem;
using TwinCAT.ValueAccess;
using (AdsClient client = new AdsClient())
{
client.Connect("172.17.60.197.1.1", 851);
AdsSymbolLoader loader = (AdsSymbolLoader)SymbolLoaderFactory.Create(client, SymbolLoaderSettings.Default);
var symbol = (IValueSymbol)loader.Symbols["TwinCAT_SystemInfoVarList._TaskInfo[1].CycleCount"];
IDisposable dispose = symbol.PollValues2(TimeSpan.FromMilliseconds(500)).Subscribe(r =>
{
Console.WriteLine($"Observed value: {r.Value}, AdsErrorCode: {r.ErrorCode}");
});
while (true)
{
var result = await symbol.ReadValueAsync(CancellationToken.None);
Console.WriteLine($"ReadValue: {result.Value}, AdsErrorCode: {result.ErrorCode}");
await Task.Delay(500);
}
}
I get such an output (no Exceptions, stopped the Remote PLC to force Error 1861):
ReadValue: 3892, AdsErrorCode: 0
Observed value: 3926, AdsErrorCode: 0
ReadValue: 3945, AdsErrorCode: 0
Observed value: 3975, AdsErrorCode: 0
ReadValue: 3997, AdsErrorCode: 0
Observed value: 4026, AdsErrorCode: 0
ReadValue: 4049, AdsErrorCode: 0
Observed value: , AdsErrorCode: 1861
Observed value: , AdsErrorCode: 1861
ReadValue: , AdsErrorCode: 1861
Observed value: , AdsErrorCode: 1861
ReadValue: , AdsErrorCode: 1861
Observed value: , AdsErrorCode: 1861
What was the incident triggering the 1861 in your case?
That's strange.
We have optional feedback for some of our basic control logic. (e.g. a cylinder can have open and close feedback but is not strict) So in the initialize routine of our debug interface, I perform a check if I can read the status of that optional IDigitalInput
symbol. And if succeeded I start a PollValues on it.
protected override async Task OnStartDetailView(IObservable<Unit> observable)
{
AtHomeSensor = await Symbol.AtHomeSensor.IsTrue.ReadValueAsync(CancellationToken.None);
if (AtHomeSensor.Succeeded)
{
DetailDisposables.Add(Symbol.AtHomeSensor.IsTrue.PollValues2(observable).Subscribe(o => { AtHomeSensor = o; }));
}
}
So in this scenario it's possbile that the IsTrue, which is a IValueSymbol<bool>
is 0 in the PLC, as it's not linked. On 6.0.194 and before I get a result wich Succeeded false and an error code. But on 6.0.216 an exception is thrown within the ReadValueAsync method.
I will create demo project to isolate the issue
A I was mislead by threading. It's not the Task<ResultReadValueAccess> ReadValueAsync(CancellationToken cancel)
method that has a regression. But it's the IObservable<T> PollValues<T>(this IValueSymbol symbol, TimeSpan period)
extension from ValueSymbolExtensions
.
But that one is intended to throw an exception because it returns the pure values. If you don't want Exceptions, than an overload producing ResultXXX objects should be used.
I don't mind exceptions, but what I find interesting is that the same code doesn't throw with 6.0.194, but does with 6.0.216.
This caused me to get trapped in a fun little rabbit hole.
But the problem I'm facing comes from a different source entirely.
In a previous issue I had a discussion with @RalfHeitmann about sharing the IObservable<Unit>
trigger between multiple PollValues
to reduce threading. And my issue has to do with that. Because in our application we have a specific debugging screen with has a lot of communication with the PLC. All done via PollValues
and sharing the same trigger source. And this screen has the ability to even add more communication load with detail views you can open or close. And upon opening a detail view, different random observables that had already started, are throwing the 1861 ADS error.
As I don't attach a error handler to the observers this is being trowed to the background thread that created them.
So there is apparently a limit to how many PollValues observables can be shared with a IObservable<Unit>
trigger source. Because having to much of them, or adding a bunch of new observables will cause timeouts on existing ones. It still seems to me something changed in the ADS source between .194 and .216 for this to become a issue for me.
Finally able to reproduce in a demo.
In the solution you find a PLC program, DemoPLC. When you run AdsTimeOutDemo after a second of 10 I get the AdsTimeOutException.
edit: If you set the debugger to break on the AdsException, you can see that it's every time a different symbol causing the timeout.
Sorry for the late answer :-( , other topics than ADS occupied me the last months. Just probed your sample code: I could reproduce the issue with Beckhoff.TwinCAT.Ads 6.0.216
With the actual Versions 6.1.86 and 6.0.302 your code seems to run as intended :-) Please reopen in case you still have problems.
I will try the new versions.
Are there noteworthy changes between 6.1 and 6.0, as I don't see any mentioning about 6.1 on infosys.
Actually, the package Version 6.1 is created with different dependencies (which still should fulfill all needs): 6.0 --> net6.0, netstandard2.0, netcoreapp3.1, net461 6.1 --> net7.0, net6.0, netstandard2.0 By now, the internal implementations are the same
The method
Task<ResultReadValueAccess> ReadValueAsync(CancellationToken cancel)
fromIValueSymbol
throws an exception if the symbol cannot be read, where an ResultReadValueAccess is expected with the failed status code.Exception message
This exception will cause the application to crash because it cannot be handled by try catch. However I expect a ResultReadValueAccess where I can check the Succeeded status, the error code and then decide what to do.
Stack trace
edit: The version I'm currently using, 6.0.216