22 Replies Latest reply on Apr 9, 2019 1:58 PM by gregor

    AFCalculation.PercentTrue is throwing random exceptions

    cteixeira

      Hi all,

       

      I'm having trouble while using AFCalculation.PercentTrue. I have a process that analyzes performance equations and searches for activations. It runs fine for a few hours, but at some random point in time, it throws this error:

       

      System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

         at OSIsoft.PI.Net.UnsafeNativeMethods.SessionManager.RPCSetupAndExecute(IntPtr sessionManager, Int32 sessionId, IntPtr package, IntPtr iob, IntPtr userToken)

         at OSIsoft.PI.Net.Connection.Invoke(OperationHandle handle, RoleEntity& principalRole)

         at OSIsoft.PI.Net.OperationHandle.Invoke()

         at OSIsoft.PI.Net.ServiceOperation.GetExpressionTime(OperationHandle handle, DateTime startTime, DateTime endTime, String expression, Int32 intervalCount, Double& matchTime, Double& percentGood)

         at OSIsoft.PI.Net.PIExpression.TimeTrue(ClientChannel channel, DateTime startTime, DateTime endTime, String expression, Int32 intervalCount, Double& percentGood)

         at OSIsoft.AF.PI.PIServer.CalculatePercentTrue(String expression, AFTimeRange timeRange, AFTimeSpan calculationInterval, AFTimeSpan MinSampleInterval, AFTimestampCalculation timeType, AFValues& PercentGoodResult)

         at OSIsoft.AF.Data.AFCalculation.PercentTrue(Object target, String expression, AFTimeRange timeRange, AFTimeSpan calculationInterval, AFTimeSpan minimumSampleInterval, AFTimestampCalculation timeType, AFValues& percentGood)

       

      The process then seems to enter an invalid state and every time I call AFCalculation.PercentTrue before that, it throws me this:

       

      System.Threading.LockRecursionException: Recursive read lock acquisitions not allowed in this mode.

         at OSIsoft.AF.PI.PIException.ConvertAndThrowException(PIServer piServer, Exception ex, String message)

         at OSIsoft.AF.PI.PIServer.CalculatePercentTrue(String expression, AFTimeRange timeRange, AFTimeSpan calculationInterval, AFTimeSpan MinSampleInterval, AFTimestampCalculation timeType, AFValues& PercentGoodResult)

         at OSIsoft.AF.Data.AFCalculation.PercentTrue(Object target, String expression, AFTimeRange timeRange, AFTimeSpan calculationInterval, AFTimeSpan minimumSampleInterval, AFTimestampCalculation timeType, AFValues& percentGood)

       

      In the machine that runs the process I have:

      PI SDK Version: 1.4.7

      AF SDK Version: 2.10.0.8628

       

      The OSIsoft.AFSDK.dll version is: 2.10.0.8628

       

      Could you please help me with this one?  Any tips would be appreciated. Thanks in advance.

        • Re: AFCalculation.PercentTrue is throwing random exceptions
          tramachandran

          Hi Carlos, would it be possible share the code snippet that you are using to invoke AFCalculation.PercentTrue method?

          It would be very helpful if you could provide the AF SDK trace and the hang dump of the application when the error is thrown.

           

          In order to better track the issue and investigate this in detail I strongly recommend that you open up a ticket with Support.

           

          Refer to:

          Capture AF SDK event trace output

          KB00046 - How to get a hang or crash dump and how to obtain and use debugging tools

          1 of 1 people found this helpful
            • Re: AFCalculation.PercentTrue is throwing random exceptions
              cteixeira

              It seems that the cases tool is offline:

               

              "We’re sorry, but we can’t process your request right now. If you need immediate assistance, please contact Technical Support."

               

              I have no problem sharing the code snippet. It's a multithreaded app that initializes a connection and starts evaluation performance equations. It initializes a connection per thread as follows:

               

                      private void InitializePIServer()
                      {
                          // get the PISystems collection for the current user and default PISystem.
                          _piServer = new PIServers().DefaultPIServer;
              
              
                          // set default for all connections to be based upon collective member's priority.
                          PIConnectionInfo.DefaultPreference = AFConnectionPreference.Any;
              
              
                          // check if the PISystem is a collective
                          if (_piServer.Collective != null)
                          {
                              // The highest priority member is given a priority of 1. Users can modify these values
                              // to any positive integer on their workstation to establish their preferred connection
                              // order. A negative priority indicates connections to that member are not allowed.
              
              
                              // stablish the highest priority to the secondary
                              _piServer.Collective.Members[PI_PRIMARY_SERVER_INDEX].Priority = 2;
                              _piServer.Collective.Members[PI_SECONDARY_SERVER_INDEX].Priority = 1;
                          }
                      }
              

               

              Then, in a loop, it starts calling what follows:

               

              public IList<AlarmEvaluation> Evaluate(AlarmDefinition alarmDefinition, DateTime lastEvaluation)
                      {
                          var evaluations = new List<AlarmEvaluation>();
              
              
                          try
                          {
                              string expression = CleanUpExpression(alarmDefinition.Expression);
              
              
                              AFTimeRange rangeToEvaluate = new AFTimeRange(
                                  new AFTime(lastEvaluation),
                                  new AFTime("*"));
              
              
                              AFTimeSpan interval = new AFTimeSpan(rangeToEvaluate.Span);
              
              
                              // IT FAILS HERE
                              AFValue value = AFCalculation.PercentTrue(
                                      _piServer,
                                      expression,
                                      rangeToEvaluate,
                                      interval,
                                      interval,
                                      AFTimestampCalculation.Auto,
                                      out AFValues percentGood)
                                  .Single();
                              
              //do more stuff...
                  }
                  catch (Exception ex)
                          {
              _logger.LogCritical(ex, $"Error while evaluating alarm definition with id '{alarmDefinition.Id}'.");
                          }
                    }
              

               

              Any help would be appreciated.

               

              Thanks in advance.

                • Re: AFCalculation.PercentTrue is throwing random exceptions
                  gregor

                  Hi Carlos,

                   

                  Can you try using a global PIServer object and to keep it alive while your application is active rather than instantiating the object each time you execute your query?

                  • Re: AFCalculation.PercentTrue is throwing random exceptions
                    Rick Davin

                    Hi Carlos,

                     

                    Is the Single() method a custom method of yours?  If so, please post that code as well.

                     

                    Note there is an AFValue.ValueAsSingle method but this is not applicable because AFCalculation.PercentTrue will return an AFValues collection and not just an AFValue.  I would suggest you break the call into another step:

                     

                    AFValues values = AFCalculation.PercentTrue( 
                            _piServer, 
                            expression, 
                            rangeToEvaluate, 
                            interval, 
                            interval, 
                            AFTimestampCalculation.Auto, 
                            out AFValues percentGood);
                    AFValue value = values.Single();
                    

                     

                    See if your code can get past the PercentTrue.  Also, your calculation interval and minimum calculation interval are the same.  Please see the remarks on this:

                     

                    Remarks

                    The caller can also control how often the expression is evaluated during the computation of the Percent True results with the MinSampleInterval argument. The server will limit the MinSampleInterval to between 1/100 and 1/10000 of the calculation period. This flexibility allows the user to manage the trade-off between accuracy and execution time. Higher accuracy typically imposes a heavier load on the server. In the extreme cases, this may impact other applications from accessing the server.

                    1 of 1 people found this helpful
                      • Re: AFCalculation.PercentTrue is throwing random exceptions
                        cteixeira

                        Single() is System.Linq. It's not related to numeric precision. Returns the first value of an IEnumerable and ensures that there's only one value. I definitely can try splitting the call but I don't think that's the problem due to the call stack you can see in the first post.

                         

                        The calculation interval and minimum interval are the same because I want to know the percentage of the time the expression has been active. So, if i've analyzed the expression 2 minutes ago, I want to know how much percentage of that 2 minute the expression evaluates to true. That's why I'm using single, because it only returns one AFValue.

                         

                        But as stated, the problem seems to be deeper.

                  • Re: AFCalculation.PercentTrue is throwing random exceptions
                    fmocke

                    I'm having the same issue.  Did make sure only one instance of PIServer is opened.  Also a multi threaded applications.

                     

                    This is a problem for me as I cannot even catch the error.  It completely crashes my application.

                     

                    Does not always happen.  Only 10% or so times it is a problem

                    • Re: AFCalculation.PercentTrue is throwing random exceptions
                      cteixeira

                      It seems that the exception is still ocurring and I'm not able to catch it or continue my workflow because being a system exception is making my process crash.

                       

                      Are there any plans to fix this issue in the upcoming releases? I'm kind of stuck with this issue.