Previous page

Next page

Locate page in Contents

Print this page

Synchronous and Asynchronous Methods

There are two basic types of methods in the Parallels Python API: synchronous and asynchronous. When a synchronous method is invoked, it completes executing before returning to the caller. An asynchronous method starts a job in the background and returns to the caller immediately.

Synchronous Methods

A typical synchronous method returns the result directly to the caller as soon as it completes executing. In the example below, the Vm.create_device() method creates and returns a new device object of the specified type. The new_dev variable receives the created object reference.

new_dev = vm.create_device(consts.PDE_OPTICAL_DISK)

Synchronous methods throw the prlsdkapi.prlsdk.ParallelsError exception.

Asynchronous Methods

Asynchronous methods in the Parallels Python API return one of the two objects: prlsdkapi.Job or prlsdkapi.Result. Methods that obtain information return the Result object. Methods that perform actions return the Job object.

A Job object is a reference to the background job that the asynchronous method has started. A job is executed in the background and may take some time to finish. In other languages, asynchronous jobs are usually handled using callbacks (or event handlers). Unfortunately, callbacks are not available in the Parallels Python API. You have two ways of handling asynchronous jobs in your application. The first one is implementing a global loop in your application and checking the results of an asynchronous job in every iteration. Another approach is to call an asynchronous method synchronously. The following explains how the second approach works.

The Job class has the wait()method. You can invoke this method as soon as you receive the Job object. What this will do is suspend the execution of your main program and wait for the job to finish. As soon as the job is finished, the wait() method will return to the caller. The results of the operation will also be ready at that time. The following code snippet illustrates this.

# Start a virtual machine. This is an asynchronous call.

job = vm.start()

  

# Wait for the job to complete.

job.wait()

  

print vm.name + " was started."

You can also use this syntax:

# Start a virtual machine, wait for the job to complete.

vm.start().wait()

  

print vm.name + " was started."

There are two main reasons why you would want to obtain a Job object from your asynchronous method as shown in the first example:

  1. You want to invoke the wait() method at some later moment.
  2. You would like to use other methods of the the Job class. The methods and properties are described in the following table:

cancel()

This method can be used to cancel the job before it is finished.

finished

This property can be used to determine the job status. True indicates that the job has finished. False indicates that the job is still running.

op_code

This property can be used to obtain a code identifying the type of the operation being performed. The property contains one of the constants from the PJOC_xxx group (the name of a constant has the PJOC_ prefix). The list of the operations is extensive. Some of the examples are: PJOC_VM_START (start a virtual machine), PJOC_VM_SUSPEND (suspend a virtual machine), etc. For the complete list of codes, see the Parallels Python API Reference guide.

As we said earlier, asynchronous methods in the Parallels Python API return either the prlsdkapi.Job object or the prlsdkapi.Result object. The Result class provides almost identical set of methods and properties as the Job class and is used similarly. An asynchronous method that returns a Result object also starts a job in the background and returns immediately to the caller. You have the same options here: loop infinitely and check if the job has completed or use the wait() function to emulate the synchronous method invocation. Consider the following example.

In this example, we will obtain the list of virtual machines registered with the given Parallels Service. The Vm.get_vm_list() method is used to perform this task. The method returns an instance of Result class populated with prlsdskapi.Vm objects. Individual Vm objects can be used to obtain information about individual virtual machines.

# Obtain a list of virtual machines.

# Wait for the asynchronous job to complete.

# On method return,  the result variable will contain

# the Result object.

result = server.get_vm_list().wait()

  

# Get the number of parameters (virtual machine objects)

# from the result object.

count = result.get_params_count()

  

# Iterate through the list and display the

# virtual machine name on the screen.

for i in range(0, count):

    vm = result.get_param(i)

    print vm.name

But what will happen if we don't use the wait() method? Let's examine this scenario. First of all, if you don't have a global loop in your program, it may simply exit before the asynchronous job is finished and you will loose the results or may experience other unpredictable problems. If you do have a loop (or some other mechanism that prevents your program from exiting) then you can do a couple of things. You can check if the job has finished by examining the finished property of either the Job or the Result object (whichever applies). If the value is True then the job has finished. If the value is False then it is still running. You can also simply try and read the data from the object. Both, the Job and the Result objects have a built-in mechanism that will invoke the wait() method automatically if you try to access them before the job is finished. Let's use the example above to illustrate this scenario.

# Obtain a list of virtual machines.

# Please note that we are not using the wait() method.

result = server.get_vm_list()

  

# This is the first time we try to access the result object, so

# the wait() method will be invoked on it automatically.

count = result.get_params_count()

  

# Iterate through the list and display the

# virtual machine name on the screen.

for i in range(0, count):

    vm = result.get_param(i)

    print vm.name

When reading the data using the class properties, you should be aware that, in most cases, the properties are using the corresponding methods of the same class to obtain the data. This means that the data may not be available locally yet and that the method invoked by a property will try to obtain it from the server side. To prevent data corruption, the wait() method will also be invoked automatically and transparently to the programmer. You should plan your application logic with this knowledge in mind.

Asynchronous methods throw the prlsdkapi.PrlSDKAsyncError exceptions.

Please send us your feedback on this help page