Calling a thread asynchronously with a callback

Duncan Booth duncan.booth at invalid.invalid
Tue Nov 28 04:13:53 EST 2006


"Diez B. Roggisch" <deets at nospam.web.de> wrote:

> Edwin Gomez wrote:
> 
>> I'm a C# developer and I'm new to Python.  I would like to know if
>> the concept of Asynchronous call-backs exists in Python.  Basically
>> what I mean is that I dispatch a thread and when the thread completes
>> it invokes a method from the calling thread.  Sort event driven
>> concept with threads. 
> 
> Counter question: does such a thing exist in C#, and if, is it bound
> to some existing event loop? 

Yes, or rather the concept exists in .Net. C# and other .Net languages 
don't actually allow pointers to functions, instead they implement 
callbacks using what are called Delegates: for each different function 
signature you need a new Delegate class, but the language compilers 
automate the process so that using Delegates becomes very similar to using 
function pointers.

In early C#:

// Delegate for function with no args and no results
public delegate void SimpleDelegate();
...
SimpleDelegate simpleDelegate = new SimpleDelegate(somefunc);
SimpleDelegate simpleDelegate = new SimpleDelegate(someobj.somefunc);
...
simpleDelegate();

C# 2.0 added the ability to declare delegates inline (i.e. anonymous 
functions), and delegate inferencing to avoid writing 'new delegatename' 
everywhere:

SimpleDelegate simpleDelegate = somefunc;

Where delegates start becoming more interesting than just function pointers 
is that all delegates support both multicasting and asynchronous callbacks.

You can add any number of functions into a delegate, and you can also 
remove functions from delegates.

Asynchronous callbacks are done by calling a delegate's BeginInvoke method. 
You have to pass this the same arguments as you would when calling the 
delegate directly, plus an AsyncCallback delegate and an object to be 
passed as part of the asynchronous response which is usually the original 
delegate. From the callback you can then call EndInvoke to get the result 
returned from the call to the function.

Now the bit you asked about: the callback happens on an arbitrary thread.

The .Net runtime maintains a thread pool to use for this sort of callback 
so it doesn't have the overhead of setting up a new thread every time. A 
lot of the system library classes support similar Beginxxx/Endxxx function 
pairs for potentially lengthy operations such as reading from a Stream, or 
performing a web request and the thread pool is also used for these.

It is fairly easy to implement a similar scheme in Python, just write a 
thread pool which gets function/argument/callback combinations from a 
queue, calls the function and then calls the callback with the response.

> I'm really curious, because having code being interrupted at any time
> by a asynchronous callback strikes me as dangerous. But then maybe I'm
> just a whimp :)

Not at all. It comes as a surprise to some people that there is no such 
thing in .Net as a single threaded program:

As well as asynchronous delegates the garbage collector uses separate 
threads: what it does is to block all threads from running while it sweeps 
the memory, compacting all moveable objects and releasing any unreferenced 
objects without finalizers. Unreferenced objects with finalizers are 
resurrected onto a list and then the garbage collector lets other threads 
run. A background thread is then used to call the finalizers for the 
collected objects and each finalizer is cleared once it has executed (so 
that unless resurrected, the next garbage collection of an appropriate 
generation can overwrite the object). What this means is that *all* 
finalizers in .Net will run on a different thread (and in arbitrary order): 
of course finalizers are pretty crippled so this may not matter.



More information about the Python-list mailing list