Working with 'Async' methods in scripting

Discussions on extending SharpCap using the built in Python scripting functionality
Post Reply
User avatar
admin
Site Admin
Posts: 13122
Joined: Sat Feb 11, 2017 3:52 pm
Location: Vale of the White Horse, UK
Contact:

Working with 'Async' methods in scripting

#1

Post by admin »

Hi,

recently I have been moving more of SharpCap's internals to an asynchronous programming model (async/await in C#, roughly equivalent to promises in Javascript, etc). If you look at the methods available on the camera object, you will see more 'Async' methods - for instance

Code: Select all

RunCaptureAsync(self: Camera, cancellationToken: CancellationToken) -> Task
CaptureSingleFrameToAsync(self: Camera, filepath: str, allowPreviousFrame: bool) -> Task[FrameCaptureResult]
TakeFramingShotAsync(self: Camera, cancellationToken: CancellationToken) -> Task
If you call these methods from scripting then they start the specified action and return a Task object that can be used to find out when the action is completed or to run more code after completion.

If you just want to start the action and don't care about completion, feel free to use the Async methods and ignore the return value. You will need to add an import so that you can access the CancellationToken type:

Code: Select all

from System.Threading import CancellationToken
SharpCap.SelectedCamera.TakeFramingShotAsync(CancellationToken.None)
If you want to do something when the action completes, do *NOT* try to use the .Wait() or .Result methods on the returned task - if you do your script will almost certainly freeze SharpCap in a deadlock. The best option is to use the version of the call without the Async - if there is one. For instance .RunCapture() rather than .RunCaptureAsync(). In those non-async methods I have dealt with any chances of deadlock, meaning that it is safe to use them, then write whatever you want to happen next as the following line of code.

If you must call an Async method and get code to run after completion, you need to use 'ContinueWith' to schedule your follow on code after the asynchronous method completes - a bit like this

Code: Select all

from System.Threading.Tasks import Task
from System.Threading import CancellationToken
from System import Action
def close(t):
 	SharpCap.SelectedCamera = None

SharpCap.SelectedCamera.TakeFramingShotAsync(CancellationToken.None).ContinueWith(Action[Task](close))
This code will take a single framing shot (assuming the camera is in still mode) and then close the camera without the risk of freezing SharpCap. Note that the 'close' function takes a Task object as a parameter but igores it. This task represents the first step of capturing the framing shot, so it will be completed by the time the continuation is called. In some cases you may wish to get the Result from this task (if it has one) to use in your continuation code.

hope this helps,

Robin
Post Reply