invokeAsynchronous Paramenters

How can I pass parameters into a funtion running inside invokeAsynchronous().

Something like this:

system.util.invokeAsynchronous(funtion(parameter1,parameter2))

Try the wrappers in later.py attached to this thread. Use it something like this:

shared.later.callAsync(project.yourModule.yourFunction, parameter1, parameter2)

If you want to stick with the built in methods and it’s all within the same scope you can simply define the variables before calling the function. This works when using standard scoping.

[code]x = 10
y = 20
def func1():
print x, y
system.util.invokeAsynchronous(func1)

output:
10 20[/code]

If you are using legacy scoping you have to do it like this.

[code]x = 10
y = 20
def func1(x=x, y=y):
print x, y
system.util.invokeAsynchronous(func1)

output:
10 20[/code]

Now if you are calling a function that is defined outside of your current scope, i.e. calling a function in a script module from an event, then I would call the function normally and do the heavy lifting asynchronously within the function.

[code]# inside shared.mymodule.mystuff

def func1(x, y):
def async():
print x, y
system.util.invokeLater(async)
system.util.invokeAsynchronous(async)

in event script

shared.mymodule.func1(10, 20)

output:
10 20[/code]

[quote=“JGJohnson”]If you want to stick with the built in methods . . .[/quote]I strongly disagree with your suggestions. Each has the user write an extra function definition by hand, implementing a very specific, repeatable, and automatable pattern. Every time you write a given algorithm from scratch, you unnecessarily introduce opportunities for bugs, and create more lines of code to maintain. Write once, call everywhere.

1 Like

Fair enough.

I was going on the assumption that joaopmrod2 was wanting to pass parameters to a local function that he/she had written. I hadn’t considered that they may be wanting to pass parameters to an existing Ingition function or Jython function.

I interpreted the question as: “I wrote a function now how do I pass params to it when I call it asynchronously.”

I believe my 3rd example covers the case of having a single function that can be called from anywhere that runs script asynchronously and accepts parameters without meeting the conditions of your disagreement. Does that example set off any warning buzzers for you?

[quote=“JGJohnson”]I believe my 3rd example covers the case of having a single function that can be called from anywhere that runs script asynchronously and accepts parameters without meeting the conditions of your disagreement. Does that example set off any warning buzzers for you?[/quote]The issue is reduced as you’ve moved the temporary function creation from caller to callee. If you have few such functions, this pattern could be reasonable. It may even be necessary in some cases (right click menu creation, in particular), but still expects the user to type nested defs for each callee.
If I recall correctly, the nested def will also slow down the outer function. Moving the work to its own function and isolating the nested def to a very short helper minimizes the slowdown.

You can create a simple wrapper function that takes the function you want to call and supplied parameters and returns a function that takes no parameters but calls the function with your desired parameters when called.

That sounds complicated but it is best to show an example.

[code]def wrap(func, *args, **kwargs) :
return lambda : func(*args,**kwargs)

def abc(a=1,b=2,c=3):
print “a=%s,b=%s,c=%s” %(a,b,c)

system.util.invokeLater(wrap(abc,10,c=11))[/code]
prints a=10,b=2,c=11

“wrap” takes a function as its first parameter, *args scoops up all the positional parameters as a list, and **kwargs scoops up all the keyword arguments as a dictionary.

func(*args, **kwargs) calls the function with the arguments flattened back out.

so calling wrap(abc,10,c=11)() is the same as calling abc(abc,10,c=11)

[quote=“sfitze”]You can create a simple wrapper function …[/quote]Which is exactly what the various utilities in later.py do, just without using the lambda syntax. And the user doesn’t have to define wrap() nor separately call both wrap() and invokeLater() in every piece of code. If you are typing the same snip of code in more than two or three places, you’re asking for maintenance miseries when something needs to change. My current iteration of later.py has

# Deferred method execution
#
# Procedures executing in the 'invokeAsynchronous' environment are not allowed
# to execute methods of gui objects.  This routine accepts a target
# function, and a variable argument list, and schedules the function call
# in the gui thread.  The function can be a bare (no parens) object method.
def callLater(func, *args, **kwargs):
	import system
	def callLaterInvoked(f=func, a=args, kw=kwargs):
		f(*a, **kw)
	system.util.invokeLater(callLaterInvoked)

(in Script “shared.util”)
With that, your example reduces to just the part unique to that usage:

def abc(a=1,b=2,c=3):
   print "a=%s,b=%s,c=%s" %(a,b,c)
   
shared.util.callLater(abc,10,c=11)

And the savings are even more significant when abc() is in a shared or project script, too.

Here is a nice explanation of invokeAsynchronous and when to use it, for people watching this thread: nickmudge.info/post/understandin … n-Ignition

A handy trick to add on to this thread. Python gives you a canned much easier way. The partial builtin can be passed to invokeAsynchronous or invokeLater and accepts all args and kwargs dynamically .

from functools import partial

def myfunc(someArg1, someArg2, optionalKwarg=None, optionalKwarg2=None):
	print someArg1, someArg2,  optionalKwarg2, optionalKwarg

# switched the kwargs just to demonstrate flexibility.
part = partial(myfunc, 'muhArg1', 'muhArg2', optionalKwarg2='options2', optionalKwarg='options1') 

system.util.invokeAsynchronous(part)
8 Likes