Polar Script is fully multi-entrance. This means that in a multi-tasking environment - such as Polar Studio - multiple script actions for multiple requests can run at the same time. This is no issue for normal procedures, for all variables will be specific and unique for the calling process. However, if you are using global variables or you are sharing class-objects over processes, you can run in to specific problems.
Dim mSettingsCache As Collection
Dim mSettingsCache_LastReadDateTime As Date
Public Function GetSettingFromCache(pContext, pSettingName As String) As String
'Force a re-read of the settings each 5 minutes
If mSettingsCache Is Nothing Or mSettingsCache_LastReadDateTime < SystemTime - TimeSerial(0, 5, 0) Then
Set mSettingsCache = New Collection
Using pContext.OpenDynamicRecordSet("SELECT Name, Value FROM Setting")
Do While Not .Eof
mSettingsCache.Add .Fields("Value").Value, .Fields("Name").Value
.MoveNext
Loop
End Using
mSettingsCache_LastReadDateTime = SystemTime
End If
Return mSettingsCache.TryGet(pSettingName, "")
End Function
In the example above, multiple routines may make use of the same cache with settings (mSettingsCache). This could lead to a situation where two entrances are filling the cache at the same time or one entance is reading the cache while the other has just cleared it.
To solve this concurrency problem, we can make use of a Lock, as shown in the modified code below. This lock ensures the code within the Lock is only entered once at a time.
Dim mSettingsCache As Collection
Dim mSettingsCache_LastReadDateTime As Date
Public Function GetSettingFromCache(pContext, pSettingName As String) As String
Using Lock
'Force a re-read of the settings each 5 minutes
If mSettingsCache Is Nothing Or mSettingsCache_LastReadDateTime < SystemTime - TimeSerial(0, 5, 0) Then
Set mSettingsCache = New Collection
Using pContext.OpenDynamicRecordSet("SELECT Name, Value FROM Setting")
Do While Not .Eof
mSettingsCache.Add .Fields("Value").Value, .Fields("Name").Value
.MoveNext
Loop
End Using
mSettingsCache_LastReadDateTime = SystemTime
End If
Return mSettingsCache.TryGet(pSettingName, "")
End Using
End Function
If the global variable mSettingsCache is used on more than one place and you want to implement 'cross-locking', you can make up your own unique name for this lock and specify this name when aquiring the lock:
Dim mSharedVariable
Function A
Using Lock("MySharedLockName")
'Use mSharedVariable here
End Using
End Function
Function B
Using Lock("MySharedLockName")
'Use mSharedVariable here
End Using
End Function
If you want, you can start a task in the background using the CallAsync statement. The background task will run while the main thread will continue running at the same time. You can use background tasks for example to do complex calculations and you do not want the main process to be waiting for this.
When calling the background-task, you may want to set up pre-cautions that this task is not started multiple times overlapping doing the same task.
The CallAsync statement cannot capture a returned value because it does not wait for the background task to complete.
Public Function MainFunction(pContext)
CallAsync BackgroundTask(pContext)
End Function
Private Function BackgroundTask(pContext)
Using Lock("", 500) 'Using a lock to prevent concurrent entrance. Waiting max 500 ms (half a second) to aquire the lock
'Do complex calculations here
End Using
End Function