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,

I have the following code:

Code: Select all

async method _Connect( cHostName as string, cUserName as string, cPassword as string ) as Task<logic>
local lReturn			as logic
local oTask				as Task

_oClient := AsyncFtpClient{ cHostName, cUserName, cPassword }
oTask := _oClient:Connect()
await oTask
lReturn := _oClient:IsConnected

return lReturn
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.

But when I call that method from another one

Code: Select all

public method Connect( cHostName as string, cUserName as string, cPassword as string ) as logic
local lReturn as logic

self:_Connect( cHostName, cUserName, cPassword )
lReturn					:= _oClient:IsConnected

return lReturn
the compiler gives me the warning

Code: Select all

warning XS4014: Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
Where is my error/misunderstanding?

Thank you very much!

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
User avatar
SHirsch
Posts: 286
Joined: Tue Jan 30, 2018 8:23 am
Location: Germany

Async question

Post by SHirsch »

Hi Wolfgang,

change to return value just to LOGIC.

Stefan
User avatar
wriedmann
Posts: 3755
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Async question

Post by wriedmann »

Hi Stefan,
thank you for your answer.
Unfortunately this does not work:

Code: Select all

error XS1983: The return type of an async method must be void, Task, Task<T>, a task-like type, IAsyncEnumerable<T>, or IAsyncEnumerator<T>
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
User avatar
SHirsch
Posts: 286
Joined: Tue Jan 30, 2018 8:23 am
Location: Germany

Async question

Post by SHirsch »

Hi Wolfgang

since you are not using the return value you can set the return type to VOID.
You are using
lReturn := _oClient:IsConnected

Otherwise you should have used
lReturn := await oTask

Stefan
User avatar
SHirsch
Posts: 286
Joined: Tue Jan 30, 2018 8:23 am
Location: Germany

Async question

Post by SHirsch »

maybe you can also change your code

Code: Select all

method _Connect( cHostName as string, cUserName as string, cPassword as string ) as logic
local lReturn			as logic
local oTask				as Task

_oClient := AsyncFtpClient{ cHostName, cUserName, cPassword }
oTask := _oClient:Connect()
oTask:Wait()
lReturn := _oClient:IsConnected
return lReturn
User avatar
wriedmann
Posts: 3755
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Async question

Post by wriedmann »

Hi Stefan,

when the return type is void, the compiler warning is gone. So I have a first solution.....

But when calling Wait() on the task, the task is not started, but waits.
I have now tried to call RunSynchronously() on the task, but that gives an exception:

Code: Select all

RunSynchronously kann nicht für eine Aufgabe aufgerufen werden, die nicht an einen Delegat gebunden ist, wie beispielsweise eine Aufgabe, die von einer asynchronen Methode zurückgegeben wird.
So I will solve with a void return value and store the return value in a property of my main object.
I have also tried with an out or ref parameter, but that does not works, as out and ref parameters are not permitted on async methods.

Thank you again - I have my solution now.

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
fxm
Posts: 53
Joined: Tue Nov 24, 2015 9:27 am
Location: Austria

Async question

Post by fxm »

wriedmann post=25446 userid=336 wrote:

Code: Select all

public method Connect( cHostName as string, cUserName as string, cPassword as string ) as logic
local lReturn as logic

self:_Connect( cHostName, cUserName, cPassword )
lReturn					:= _oClient:IsConnected

return lReturn
One solution would be to get the result of the call to _Connect

Code: Select all

public method Connect( cHostName as string, cUserName as string, cPassword as string ) as logic
local lReturn as logic
local lConnectResult as logic

lConnectResult := self:_Connect( cHostName, cUserName, cPassword ):Result
lReturn					:= _oClient:IsConnected

return lReturn
or probably just

Code: Select all

public method Connect( cHostName as string, cUserName as string, cPassword as string ) as logic
local lReturn as logic

lReturn := self:_Connect( cHostName, cUserName, cPassword ):Result

return lReturn
User avatar
wriedmann
Posts: 3755
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Async question

Post by wriedmann »

Hi Fergus,
the problem stays in the fact that the async method cannot return anything other than a void or task value.
If I can store the result in another place my code compiles without warning or error.
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
fxm
Posts: 53
Joined: Tue Nov 24, 2015 9:27 am
Location: Austria

Async question

Post by fxm »

wriedmann post=25454 userid=336 wrote:Hi Fergus,
the problem stays in the fact that the async method cannot return anything other than a void or task value.
If I can store the result in another place my code compiles without warning or error.
Wolfgang
I think I must have missed the point. In any case, this code compiles without warnings..

Code: Select all

USING System
USING System.Collections.Generic
USING System.Linq
USING System.Text
using System.Threading.Tasks

FUNCTION Start() AS VOID STRICT
    
    Console.WriteLine("Hello World!")

    LOCAL t AS Test
    t := Test{}
    t:Connect()
    
    Console.ReadKey()

CLASS Test

ASYNC METHOD _Connect() AS Task<LOGIC>

AWAIT Task.Delay(1000)

RETURN TRUE

METHOD Connect AS LOGIC

LOCAL lReturn AS LOGIC 

lReturn := SELF:_Connect():Result

RETURN lReturn

END CLASS

HansjoergP
Posts: 142
Joined: Mon Jul 25, 2016 3:58 pm
Location: Italy

Async question

Post by HansjoergP »

Your call self:_Connect needs an await. If you need an synchronous call you can use
self:_Connect( cHostName, cUserName, cPassword ).Result
With the Result Call you have to be carefull, because in some situation it can result in an dead lock
Post Reply