xsharp.eu • Async question
Page 1 of 5

Async question

Posted: Wed Mar 01, 2023 12:53 pm
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

Async question

Posted: Wed Mar 01, 2023 1:49 pm
by SHirsch
Hi Wolfgang,

change to return value just to LOGIC.

Stefan

Async question

Posted: Wed Mar 01, 2023 1:54 pm
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

Async question

Posted: Wed Mar 01, 2023 2:26 pm
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

Async question

Posted: Wed Mar 01, 2023 2:31 pm
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

Async question

Posted: Wed Mar 01, 2023 2:53 pm
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

Async question

Posted: Wed Mar 01, 2023 2:54 pm
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

Async question

Posted: Wed Mar 01, 2023 2:59 pm
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

Async question

Posted: Wed Mar 01, 2023 3:38 pm
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


Async question

Posted: Wed Mar 01, 2023 3:57 pm
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