User bio
404 bio not found
Member since Oct 24, 2022
Posts:
Replies:
I finally managed to solve the problem in Python. It's not perfect but it works:
Class User.Timer Extends %RegisteredObject
{
Property Executor [ Private ];
Method Initialize(maxWorkers As %Integer = 4) [ Language = python ]
{
import concurrent.futures
import time
import threading
self.Executor = concurrent.futures.ThreadPoolExecutor(max_workers=maxWorkers)
}
Method Close() [ Language = python ]
{
if self.Executor:
self.Executor.shutdown()
}
Method Greet(name)
{
Write "Hello ", name, !
}
Method OnCallback0(methodName As %String) [ Private ]
{
Do $METHOD(instance, methodName)
}
Method OnCallback1(instance As %RegisteredObject, method As %String, arg1) [ Private ]
{
Do $METHOD(instance, method, arg1)
}
Method OnCallback2(instance As %RegisteredObject, method As %String, arg1, arg2) [ Private ]
{
Do $METHOD(instance, method, arg1, arg2)
}
Method OnCallback3(instance As %RegisteredObject, method As %String, arg1, arg2, arg3) [ Private ]
{
Do $METHOD(instance, method, arg1, arg2, arg3)
}
Method OnCallback4(instance As %RegisteredObject, method As %String, arg1, arg2, arg3, arg4) [ Private ]
{
Do $METHOD(instance, method, arg1, arg2, arg3, arg4)
}
Method OnCallback5(instance As %RegisteredObject, method As %String, arg1, arg2, arg3, arg4, arg5) [ Private ]
{
Do $METHOD(instance, method, arg1, arg2, arg3, arg4, arg5)
}
Method InternalRun(delayMs As %Integer, wait As %Boolean, instance As %RegisteredObject, method As %String, args... As %List) [ Internal, Language = python ]
{
import time
import iris
if not self.Executor:
raise Exception("The 'Initialize' method has not been called.")
def worker_function():
time.sleep(delayMs / 1000)
if len(args) == 0:
self.OnCallback0(instance, method)
elif len(args) == 1:
self.OnCallback1(instance, method, args[0])
elif len(args) == 2:
self.OnCallback2(instance, method, args[0], args[1])
elif len(args) == 3:
self.OnCallback3(instance, method, args[0], args[1], args[2])
elif len(args) == 4:
self.OnCallback4(instance, method, args[0], args[1], args[2], args[3])
elif len(args) == 5:
self.OnCallback5(instance, method, args[0], args[1], args[2], args[3], args[4])
else:
raise Exception("Too many arguments.")
return 0
future = self.Executor.submit(worker_function)
# wait == 0 means fire-and-forget
try:
if (wait == 1):
rv = future.result()
except Exception as e:
print(f"{e}")
}
/// delayMs - the parameter specifies the timer delay in milliseconds
/// wait - if the parameter is false, the process will not wait for the Future result to be returned (fire-and-forget)
/// instance - any object which method should be called with a delay
/// method - specifies the object's callback method name
/// args - the callback method arguments (up to 5)
Method Run(delayMs As %Integer, wait As %Boolean, instance As %RegisteredObject, method As %String, args... As %List)
{
Do ..InternalRun(delayMs, wait, instance, method, args...)
}
ClassMethod Test()
{
Set obj = ##class(Timer).%New()
Do obj.Initialize()
Do obj.Run(1000, 0, obj, "Greet", "John")
Do obj.Run(2000, 0, obj, "Greet", "Jessica")
Write "If 'wait == 0' this line will be printed first", !
Do obj.Close()
}
}
Hi Alexey, that's the point! I expect the following sequence:
- the worker is created in background and waits for, say, 5 seconds. The main thread isn't blocked!
- the program prints "This should be printed first"
- the waiting interval of 5 seconds expires and the worker emits its own message
Certifications & Credly badges:
Dmitrii has no Certifications & Credly badges yet.
Global Masters badges:
Dmitrii has no Global Masters badges yet.
Followers:
Dmitrii has no followers yet.
Following:
Dmitrii has not followed anybody yet.
Hi Tani and thanks a lot for the info! To avoid struggling with interprocess communication, I experimented a little more and ended up with Workers and Python (see below). I'd appreciate your opinion