Multithreading – asynccall and Delphi 2007
What I basically want is to start asynccall and continue my code loading I have an interface part that consumes a lot of time (600 ms) and I want to load this code in a separate thread
I tried to use asynccall to do something like this:
procedure Load; begin ... end; initialization AsyncCall(@Load,[]); // or LocalAsyncCall(@Load)
However, this load process is actually started in the main thread, not in the newly created thread How do I force the load process to load into any thread other than mainthread?
I can create a TThread and execute this, but I want to force asynccall or localasynccall or any work from the asynccall library
Thanks for your help.
Solution
The problem is that your code does not retain the iasynccall interface returned by the asynccall function
AsyncCall(@Load,[]); //AsyncCall returns an IAsyncCall interface,//but this code does not take a reference to it
Therefore, once the initialization part is completed, the reference count of the returned interface is decremented to zero This frees the object that implements the interface to do so:
destructor TAsyncCall.Destroy; begin if FCall <> nil then begin try --> FCall.Sync; // throw raised exceptions here finally FCall.Free; end; end; inherited Destroy; end;
The key is to call sync to force the asynchronous call to be completed All this happens in the main thread, which explains the behavior you report
The solution is that you only need to store the iasynccall interface in a variable
var a: IAsyncCall; initialization a := AsyncCall(@Load,[]);
In real code, you need to ensure that load is complete before running any load - dependent code When your program reaches the required loading location, you must call sync on the iasynccall interface
So you might write something like this
unit MyUnit; interface procedure EnsureLoaded; implementation uses AsyncCalls; .... procedure Load; begin .... end; var LoadAsyncCall: IAsyncCall; procedure EnsureLoaded; begin LoadAsyncCall := nil;//this will effect a call to Sync end; initialization LoadAsyncCall := AsyncCall(@Load,[]); end.
Invoke ensureloaded. From other units that need to be loaded and run Or, any method exported by myunit that depends on the run load calls ensureloaded The latter option has better encapsulation