|
|
(2 intermediate revisions by one other user not shown) |
Line 1: |
Line 1: |
| ===What are Asynchronous Functions?===
| | #REDIRECT [[Asynchronous Methods]] |
| [[Image:Async_Functions_Flowchart.png|200px|link=|right|thumb|'''Click to Enlarge''']] | |
| Asynchronous functions are a way to queue up calls to your VINT devices without waiting for return codes. This allows your program to carry on as quickly as possible after setting a property on a VINT device.
| |
| | |
| They are comprised of two parts: the function call, and the ''async handler''. In order to use asynchronous function calls, you will call the function to do something with a Phidget channel, and assign said function an ''async handler''. The function call will queue up the related communications and return immediately. The ''async handler'' will be called once the relevant communications have been completed to provide the return code from the Phidget.
| |
| | |
| Asynchronous calls issued at the same time to multiple VINT channels may be dispatched in quick succession before the Phidget22 back-end waits for return codes from any of the channels. This can significantly reduce latency when talking to multiple VINT channels.
| |
| | |
| Multiple asynchronous calls to the same channel in rapid succession will be queued up and issued one at a time as return codes are received for each.
| |
| | |
| Since these function calls are queued up, if you issue asynchronous calls faster than they can be dispatched and fully handled, they will begin to back up and potentially ''add'' latency to your program (even though your program will continue seamlessly queueing async commands). In extreme cases, if you queue up enough asynchronous calls, newer calls will be dropped, and your ''async handler'' will complete with ''Phidget Error 0x10 NoSpace''. If you start seeing these errors in your ''async handler'', you should re-evaluate your program and figure out how to make fewer calls to the asynchronous functions.
| |
| | |
| ===Ideas for Regulating Asynchronous Function Calls===
| |
| To help you get started on deciding ways to prevent your application from overloading the asynchronous function call buffers, we have provided the following example, to both serve as a functional program, and as an outline for other languages.
| |
| | |
| This program uses a simple method of using the ''async handler'' to count the number of completed functions, and compares it to the number of asynchronous calls that were issued. The program will not call more asynchronous functions until all previous calls have completed, all while not blocking the rest of the loop in the process.
| |
| | |
| This example is intended to demonstrate how you could, for example, update the state of an output from within a very fast control loop, without slowing down either the update rate of the output, or the control loop itself.
| |
| | |
| See the [https://www.phidgets.com/?view=api API page] for your device for a simpler example of how to use asynchronous functions from within your application, or for examples in languages not included here.
| |
| | |
| <tabber>
| |
| Python=
| |
| <syntaxhighlight lang=python>
| |
| from Phidget22.Phidget import *
| |
| from Phidget22.Devices.DigitalOutput import *
| |
| from Phidget22.ErrorCode import *
| |
| import time
| |
| | |
| def main():
| |
| digitalOutput0 = DigitalOutput()
| |
| | |
| digitalOutput0.openWaitForAttachment(5000)
| |
| | |
| #Assign new variables to track the number of calls made vs completed
| |
| digitalOutput0.AsyncCalls = 0
| |
| digitalOutput0.AsyncComplete = 0
| |
| def AsyncResult(ch, res, details):
| |
| ch.AsyncComplete += 1
| |
| print("Async Complete:" + str(ch.AsyncComplete))
| |
| if res != ErrorCode.EPHIDGET_OK:
| |
| print("Async failure: %i : %s" % (res, details))
| |
|
| |
| while(1): #some loop condition
| |
| #Here we check if the previous asynchronous call has completed before issuing a new one
| |
| #If you had multiple asynchronous calls to make, you could (for example) give each its
| |
| #own counter, or call a new batch of them once an entire set completes
| |
| if(digitalOutput0.AsyncCalls == digitalOutput0.AsyncComplete):
| |
| digitalOutput0.AsyncCalls += 1
| |
| digitalOutput0.setDutyCycle_async(1, AsyncResult)
| |
| # NOTE: Make sure to wait for async call to complete before closing the channel
| |
|
| |
| #Do other work here...
| |
|
| |
| | |
| digitalOutput0.close()
| |
| | |
| main()
| |
| </syntaxhighlight>
| |
| |-|
| |
| Java=
| |
| <syntaxhighlight lang=java>
| |
| import com.phidget22.*;
| |
| import java.io.IOException;
| |
| | |
| public class JavaApplication11 {
| |
| | |
| static int asyncCalls = 0;
| |
| static int asyncComplete = 0;
| |
|
| |
| public static void main(String[] args) throws Exception {
| |
|
| |
| Phidget.resetLibrary();
| |
| DigitalOutput digitalOutput0 = new DigitalOutput();
| |
| | |
| digitalOutput0.open(5000);
| |
|
| |
| while(asyncComplete < 1000) { //Some loop condition
| |
| //Here we check if the previous asynchronous call has completed before issuing a new one
| |
| //If you had multiple asynchronous calls to make, you could (for example) give each its
| |
| //own counter, or call a new batch of them once an entire set completes
| |
| if(asyncCalls == asyncComplete) {
| |
| asyncCalls++;
| |
| digitalOutput0.setDutyCycle(1, new AsyncListener() {
| |
| public void onAsyncCallback(AsyncResult ar) {
| |
| if (ar.getReturnCode() == ErrorCode.SUCCESS) {
| |
| asyncComplete++;
| |
| System.out.println("Async Complete: " + asyncComplete);
| |
| }
| |
| else
| |
| System.out.println("Async Failure: " + ar);
| |
| }
| |
| });
| |
| // NOTE: Make sure to wait for async call to complete before closing the channel
| |
| }
| |
|
| |
| //Do other work here...
| |
| Thread.sleep(1);
| |
| }
| |
| | |
| digitalOutput0.close();
| |
| }
| |
| }
| |
| </syntaxhighlight>
| |
| |-|
| |
| C#=
| |
| <syntaxhighlight lang=cSharp>
| |
| using System;
| |
| using Phidget22;
| |
| | |
| namespace ConsoleApplication
| |
| {
| |
| class Program
| |
| {
| |
| static void Main(string[] args)
| |
| {
| |
| DigitalOutput digitalOutput0 = new DigitalOutput();
| |
| | |
| digitalOutput0.Open(5000);
| |
| | |
| digitalOutput0.DutyCycle = 1;
| |
| | |
| int asyncCalls = 0;
| |
| int asyncComplete = 0;
| |
| double dutyCycle = 0.1;
| |
| while (true) /* Some loop condition */
| |
| {
| |
| //Here we check if the previous asynchronous call has completed before issuing a new one
| |
| //If you had multiple asynchronous calls to make, you could (for example) give each its
| |
| //own counter, or call a new batch of them once an entire set completes
| |
| if (asyncCalls == asyncComplete)
| |
| {
| |
| asyncCalls++;
| |
| digitalOutput0.BeginSetDutyCycle(dutyCycle, delegate (IAsyncResult result)
| |
| {
| |
| try
| |
| {
| |
| asyncComplete++;
| |
| digitalOutput0.EndSetDutyCycle(result);
| |
| Console.WriteLine("Async Complete: " + asyncComplete.ToString());
| |
| }
| |
| catch (PhidgetException ex)
| |
| {
| |
| Console.WriteLine("Async Failure: " + ex.Message);
| |
| }
| |
| }, null);
| |
| }
| |
| | |
| /*
| |
| * Do other work were
| |
| */
| |
| }
| |
| digitalOutput0.Close();
| |
| }
| |
| }
| |
| }
| |
| </syntaxhighlight>
| |
| |-|
| |
| C=
| |
| <syntaxhighlight lang=c>
| |
| #include <phidget22.h>
| |
| #include <stdio.h>
| |
| | |
| void CCONV setDutyCycleDone(PhidgetHandle phid, void *ctx, PhidgetReturnCode res) {
| |
| int *asyncComplete = (int*)ctx;
| |
| (*asyncComplete)++;
| |
| printf("Async Complete : %d\n", *asyncComplete);
| |
| }
| |
| | |
| int main() {
| |
| PhidgetDigitalOutputHandle digitalOutput0;
| |
| int asyncComplete;
| |
| int asyncCalls;
| |
| | |
| PhidgetDigitalOutput_create(&digitalOutput0);
| |
| | |
| Phidget_openWaitForAttachment((PhidgetHandle)digitalOutput0, 5000);
| |
| | |
| PhidgetDigitalOutput_setDutyCycle(digitalOutput0, 1);
| |
| | |
| asyncComplete = 0;
| |
| asyncCalls = 0;
| |
| while (1) { //Some loop condition
| |
| | |
| //Here we check if the previous asynchronous call has completed before issuing a new one
| |
| //If you had multiple asynchronous calls to make, you could (for example) give each its
| |
| //own counter, or call a new batch of them once an entire set completes
| |
| if (asyncCalls == asyncComplete) {
| |
| asyncCalls++;
| |
| PhidgetDigitalOutput_setDutyCycle_async(digitalOutput0, 1, setDutyCycleDone, &asyncComplete);
| |
| }
| |
| | |
| //Do other work here...
| |
| | |
| }
| |
| Phidget_close((PhidgetHandle)digitalOutput0);
| |
| | |
| PhidgetDigitalOutput_delete(&digitalOutput0);
| |
| }
| |
| </syntaxhighlight>
| |
| </tabber>
| |