I have a model object that runs long operations. I'm trying to run some of these operations in threads to keep the interface responsive, download 2 things at once, etc, but I want to hide these details from the interface code as much as possible. I'm trying to use the AsyncCall library, but having issues.
type EUpdaterAction = (auFoundCurrentVersion, auFoundUpdateVersion);
type
TUpdater = class
public
procedure loadCurrentVersion();
procedure notify(action: EUpdaterAction);
end;
procedure TUpdater.loadCurrentVersion();
begin
TAsyncCalls.Invoke(procedure
begin
Assert(Windows.GetCurrentThreadId() <> System.MainThreadID);
//Really long code
TAsyncCalls.VCLSync(procedure begin notify(auFoundCurrentVersion); end);
end);
end;
The assertion fails. Do I need to do something to make it run in a separate thread, or does the first example shown with the library just not actually run in threads?
You need to call IAsyncCall.ForceDifferentThread
to force the code to run in a different thread. In your example the interface that TAsyncCalls.Invoke() returns is released immediately because the function ends and releasing the IAsyncCall interface calls the Sync
method. And because your task hasn't started yet, the Sync
method will execute it in the same thread, unless the ForceDifferentThread
method was called.
TAsyncCalls.Invoke(procedure
begin
Assert(Windows.GetCurrentThreadId() <> System.MainThreadID);
//Really long code
TAsyncCalls.VCLSync(procedure begin notify(auFoundCurrentVersion); end);
end).ForceDifferentThread; // <<<<<
But is that really what you want? I guess you want to keep the thread alive after loadCurrentVersion() has exited. And for this AsyncCalls isn't the right tool.