Page 2 of 5
Async question
Posted: Wed Mar 01, 2023 4:06 pm
by wriedmann
Hi Hansjörg,
Your call self:_Connect needs an await. If you need an synchronous call you can use
but I have the await already inside the _Connect() method.... so this method should wait until the task (_oClient:Connect()) is finished.
If I add another await statement I need to step that up to the top level. After all, one of the methods need to be called by a VO program over the COM interface.
Wolfgang
Async question
Posted: Wed Mar 01, 2023 4:39 pm
by wriedmann
Hi Hansjörg,
you are right: the await keyword does not stops the execution on the main thread until the task completes, but returns immediatly to the caller.
That is not what I need.
The Connect() call now works, but another call (ListDirectory) does not goes over the await line, but blocks there.
Really, I feel I'm too stupid for this - maybe I should leave programming to real professionals.
Wolfgang
Async question
Posted: Wed Mar 01, 2023 4:46 pm
by Chris
Hi Wolfgang,
I'll join you in that, I never, ever understood the ASYNC/AWAIT concept
Async question
Posted: Wed Mar 01, 2023 4:55 pm
by leon-ts
Hello Wolfgang,
wriedmann post=25446 userid=336 wrote:
To be able to use the "await" keyword I need to flag the method as async.
If I understand that correctly, this method returns only when the task is finished.
No! The AWAIT statement does not wait for the operation to complete, but returns control to the calling code, where execution continues from the next line (see screenshot).
- screenshot1.png (71.17 KiB) Viewed 706 times
After the operation on the AWAIT line is completed, control will return to the _Connect method on the next line after the AWAIT statement. That is, the AWAIT operation is run as a background thread (although it is claimed that this is not always the case, and in some cases the compiler simply simulates asynchronous operation with jump commands).
In your example, the Connect method (without the underscore) is essentially trying to read the IsConnected property immediately without waiting for the asynchronous task to complete. And the code continues executing by exiting the Connect method. This leads to unpredictable consequences.
Best regards,
Leonid
Async question
Posted: Wed Mar 01, 2023 5:06 pm
by wriedmann
Hi Leonid,
ok, so I'm again totally wrong.
"await" means that the execution should NOT wait, but continue. Then it makes sense that the calling method must be flagged as "async".
But then after this call I should be able to loop with sleep statements until the background task is finished, doing somethings like this:
Code: Select all
self:_ListDirectory( cPath )
while _lSuccess == false
System.Diagnostics.Debug.WriteLine( "Waiting on ListDirectory" )
System.Threading.Thread.Sleep( 100 )
end
if _lSuccess
oReturn := _oEntryList
endif
But the strange thing is that the in the called method the code is never executed (I have traced that with Debug.WriteLine() calls):
Code: Select all
_lSuccess := false
System.Diagnostics.Debug.WriteLine( "creating task" )
oTask := _oClient:GetListing( cSearch, FtpListOption.AllFiles )
System.Diagnostics.Debug.WriteLine( "awaiting task" )
await oTask
System.Diagnostics.Debug.WriteLine( "task finished" )
_lSuccess := true
The "task finished" message never arrives, and the _lSuccess is never set to true.
Wolfgang
Async question
Posted: Wed Mar 01, 2023 5:12 pm
by wriedmann
Hi Leonid,
theoretically (at least for a dummy like me) is should be relatively easy to do:
I would only like to start something in the background and check periodically in the foreground if the background process is finished.
But it seems that this is not possible.
So I have to give up on that and search something other.
Wolfgang
P.S. strange enough, in a WPF environment that works
Async question
Posted: Wed Mar 01, 2023 5:45 pm
by leon-ts
Hi Wolfgang,
If this is a GUI application, then upon completion of the asynchronous task (next line, after the AWAIT statement), you can try send a notification message to the window; having received it in the Dispatch method, you will know that the operation has completed and do something about it.
Code: Select all
_oClient := AsyncFtpClient{ cHostName, cUserName, cPassword }
oTask := _oClient:Connect()
await oTask
PostMessage(SomeWndHandle, WM_USER + ..., IIF(_oClient:IsConnected, 1, 0), 0)
The line after AWAIT is executed on the main thread, so interacting with the GUI is safe.
P.S. I didn't do such interactions (notifying the window when an asynchronous operation has completed). I prefer to work with classic threads.
Best regards,
Leonid
Async question
Posted: Wed Mar 01, 2023 5:53 pm
by wriedmann
Hi Leonid,
unfortunately this is not a GUI application - I need that for a COM library.
The FTPS library I use has two families of methods: synchronous and asynchronous.
Until now, I have only used the synchronous methods, and they work well. But for longer transfers I need a sort of progress comunication, and I have failed to implement that with COM callbacks.
Then I have tried to use the asynchronous methods - normally much better suited for network operations.
I will try your suggestion, but it seems that at least the GetListing() call stops in the await and never goes forward, even if I make the main thread sleep.
Wolfgang
Async question
Posted: Wed Mar 01, 2023 8:42 pm
by NickFriend
Hi Wolfgang,
I'm not entirely sure what exactly you need to achieve, but if the idea is to call _oClient:Connect(), then call _ListDirectory when the Connect call has completed, all you need to do is to place the _ListDirectory() call on the line after your await statement.
As Leonid pointed out, the "awaited" method will be started and run in the background. In the meantime application control returns to the calling method. Then as soon as the awaited method completes it will resume execution with the code following the await call.
Our app uses async/await very extensively and once you get the pattern clear in your head it works absolutely seamlessly and the code is much clearer than the older style BackgroundWorker.
Nick
Async question
Posted: Thu Mar 02, 2023 4:58 am
by wriedmann
Hi Nick,
what can I do in the main thread to wait until the background/async thread finishes?
Thank you very much!
Wolfgang