Syntax for Consuming .NET Delegates

In PowerBuilder .NET, you can use PowerScript to invoke delegates in imported assemblies either synchronously or asynchronously.

Delegate declaration

This C# syntax declares delegate types named Func and FuncAsync in a .NET assembly that you import to your PowerBuilder .NET target.

.NET class declaration in C# (in an external assembly):
                   using System;
                   delegate double Func(double x);
                   delegate double FuncAsync(double[] a);

The example for the synchronous use case that follows consumes the Func delegate, and the example for the asynchronous use case consumes the FuncAsync delegate.

Synchronous use case

This PowerScript syntax uses the delegate type Func from the external DLL that you import to your target. The delegate signature requires a function that takes a double datatype and returns a value with a double datatype.
                public function double[]  of_apply  (double a_v[], Func a_f)
                     double result[]
                     for  i = 0 to i < a_v.Length step 1
                          result[i] = a_f (a_v[i])
                      next
                          return result
                end function
                
               public function double of_multiply(double a_x)                 
	                    return a_x * factor;
                end function          
                 public subroutine of_test()
                      double a[] = {1.0,2.0,3.0,4.0,5.0}
                      double doubles[] =  of_apply(a, of_multiply)
                end subroutine

In the above example, the of_test method has a vector of double values. The vector is passed to the function of_apply which calls the function of_multiply for each value in the vector using the delegate variable a_f. This is possible since of_apply takes a delegate as an argument (a_f).

You can use the above method to apply different algorithms to the same data. Instead of directly calling of_multiply, you can include additional functions with of_apply and the delegate variable, as long as the additional functions process a single value of the double datatype and return a value of the double datatype.

Asynchronous use case

This PowerScript syntax uses the delegate type FuncAsyc from the external DLL that you import to your target:
                public function double of_sum( double a_v[] )
                     double sum
                     for  i = 0 to i < a_v.Length step 1
                          sum = sum + a_v[i]
                      next
                          return sum
                end function
                
                 public subroutine test()
                      double a[] = {1.0,2.0,3.0,4.0,5.0}
                      FuncAsync D = of_sum
                      System.AsyncCallback nullValue
                      integer stateValue
                      System.IAsyncResult ar = D.BeginInvoke( a, nullValue, stateValue ) 
                      //background thread starts
                      ...  
                      double result = D.EndInvoke( ar ) // wait for thread to return 
                      result (join)
                end subroutine

The above example corresponds to a "wait-until-done pattern." You can also use asynchronous processing in a "polling pattern," where the invoked thread is polled to determine whether it is finished, or in a "callback pattern," where a callback function is called when the thread has finished executing.

The code between BeginInvoke and EndInvoke runs in the main thread, but the computation of the sum has its own thread from the .NET thread pool. When EndInvoke is called, it acts as a Join operation and completes when the sum is returned by the child thread.
Note: To maintain thread safety, .NET prevents child threads from directly getting or setting property values in a form or its child controls. You can read from and write to the user interface only from the main UI thread.