Async question

This forum is meant for questions and discussions about the X# language and tools
User avatar
wriedmann
Posts: 3755
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Async question

Post 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
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
User avatar
wriedmann
Posts: 3755
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Async question

Post 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
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
User avatar
Chris
Posts: 4898
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Async question

Post by Chris »

Hi Wolfgang,

I'll join you in that, I never, ever understood the ASYNC/AWAIT concept :)
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
leon-ts
Posts: 435
Joined: Fri Feb 03, 2017 1:43 pm

Async question

Post 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
screenshot1.png (71.17 KiB) Viewed 703 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
Best regards,
Leonid
User avatar
wriedmann
Posts: 3755
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Async question

Post 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
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
User avatar
wriedmann
Posts: 3755
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Async question

Post 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
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
leon-ts
Posts: 435
Joined: Fri Feb 03, 2017 1:43 pm

Async question

Post 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
Best regards,
Leonid
User avatar
wriedmann
Posts: 3755
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Async question

Post 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
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
NickFriend
Posts: 248
Joined: Fri Oct 14, 2016 7:09 am

Async question

Post 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
User avatar
wriedmann
Posts: 3755
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Async question

Post 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
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Post Reply