Welcome, Guest
Username: Password: Remember me

TOPIC:

Async question 02 Mar 2023 08:04 #25479

  • HansjoergP
  • HansjoergP's Avatar


  • Posts: 77
  • If it is not a GUI thread. Then the .Result call should work. The Result call blocks the execution until the result is available. You have to be carefull, because depending on your thread it can result to an deadlock.
    Another possibility would be "Task.Run( () => asyncMethod()).Wait();"

    async/await is a great thing, but everything with parallel execution requires a lot of attention and sometimes it is really hard to understand

    learn.microsoft.com/en-us/dotnet/standar...-a-value-from-a-task
    stackoverflow.com/questions/17248680/awa...sult-hangs-deadlocks

    Please Log in or Create an account to join the conversation.

    Async question 02 Mar 2023 08:05 #25480

    • robert
    • robert's Avatar


  • Posts: 3600
  • Wolfgang,
    If you want the main thread to wait until the asynchronous code finishes, then you are making things sychronous and your app will "halt" while the background code is running.
    The whole idea about asynchronous is that the main thread will NOT wait and will be free for the user.

    Robert
    XSharp Development Team
    The Netherlands

    Please Log in or Create an account to join the conversation.

    Async question 02 Mar 2023 08:12 #25482

    • wriedmann
    • wriedmann's Avatar
    • Topic Author


  • Posts: 3367
  • Hi Robert,
    my main problem is that in the async version of the class all calls are async, even the one I don't like to have async, like connect, change directory, directory listing, current directory and so forth. I would like to have async only the transfer methods (upload and download).
    Wolfgang
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    Async question 02 Mar 2023 08:22 #25483

    • HansjoergP
    • HansjoergP's Avatar


  • Posts: 77
  • Please Log in or Create an account to join the conversation.

    Async question 02 Mar 2023 08:26 #25484

    • robert
    • robert's Avatar


  • Posts: 3600
  • Wolfgang,
    Inside Visual Studio we sometimes have the same problem.
    In those cases we use a helper method from the ThreadHelpers JoinableTaskFactory.
    That looks like this:
                ThreadHelper.JoinableTaskFactory.Run(async delegate
                    {
                        await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
                        using (new AutomationScope(this.project.Site))
                        {
                            project.SetEditLabel(value);
                        }
                    });

    I think you can do something similar with the Task.Run method.

    Robert
    XSharp Development Team
    The Netherlands

    Please Log in or Create an account to join the conversation.

    Async question 02 Mar 2023 08:48 #25485

    • wriedmann
    • wriedmann's Avatar
    • Topic Author


  • Posts: 3367
  • Hi Hansjörg,

    thank you very much, this lik is also helpful to understand the concept better:
    blog.stephencleary.com/2012/02/async-and-await.html
    Wolfgang
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    Async question 02 Mar 2023 08:49 #25486

    • wriedmann
    • wriedmann's Avatar
    • Topic Author


  • Posts: 3367
  • Hi Robert,
    I will look into it and then post the code here (if I am able to make it work).
    Thank you very much!
    Wolfgang
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    Async question 02 Mar 2023 09:23 #25487

    • SHirsch
    • SHirsch's Avatar


  • Posts: 279
  • Hi all,

    here is a good description of asynchronos programming:
    learn.microsoft.com/en-us/dotnet/csharp/...hronous-programming/

    Stefan

    Please Log in or Create an account to join the conversation.

    Async question 02 Mar 2023 09:52 #25488

    • wriedmann
    • wriedmann's Avatar
    • Topic Author


  • Posts: 3367
  • Hi,
    I have something very strange. Please see this code:
    oStopwatch := System.Diagnostics.Stopwatch{}
    oStopwatch:Start()
    Task.Run( { => self:_ConnectA( cHostName, cUserName, cPassword, nPort, oConfig ) } )
    while _lWorking
    	System.Threading.Thread.Sleep( 10 )
    	if oStopwatch:Elapsed:Seconds > _nTimeout
    		_cErrorMessage			:= "Timeout " + _nTimeout:ToString()
    		exit
    	endif
    end
    _DebOut( "Waited " + oStopwatch:Elapsed:ToString() )
    and the called code is
    _DebOut( "Creating AsyncFtpClient" )
    _oClient			:= AsyncFtpClient{ cHostName, cUserName, cPassword, nPort, oConfig }
    _DebOut( "Creating Task Connect()" )
    oTask				:= _oClient:Connect()
    _DebOut( "Awaiting Task Connect()" )
    await oTask
    _DebOut( "Task Connect() finished" )
    The really strange thing is the sequence:
    Waited 00:00:00.0029780
    Client is null
    Creating AsyncFtpClient
    Creating Task Connect()
    Awaiting Task Connect()
    Task Connect() finished
    This means that first the rest of the method is executed before the task is started!
    I'm now searching a possibility to make my method wait and let the task run in the background.
    Wolfgang
    P.S. even this call does not resolves:
    Task.WhenAll( self:_ConnectA( cHostName, cUserName, cPassword, nPort, oConfig ) )
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    Async question 02 Mar 2023 09:54 #25489

    • NickFriend
    • NickFriend's Avatar


  • Posts: 246
  • Hi Wolfgang,

    What Robert said - you need to un-async your async ;-)

    The following class will do what you want.
    public static class AsyncHelpers
        {
            /// <summary>
            /// Executes an async Task<T> method which has a void return value synchronously
            /// </summary>
            /// <param name="task">Task<T> method to execute</param>
            public static void RunSync(Func<Task> task)
            {
                var oldContext = SynchronizationContext.Current;
                var synch = new ExclusiveSynchronizationContext();
                SynchronizationContext.SetSynchronizationContext(synch);
                synch.Post(async _ =>
                {
                    try
                    {
                        await task();
                    }
                    catch (Exception e)
                    {
                        synch.InnerException = e;
                        throw;
                    }
                    finally
                    {
                        synch.EndMessageLoop();
                    }
                }, null);
                synch.BeginMessageLoop();
    
                SynchronizationContext.SetSynchronizationContext(oldContext);
            }
    
            /// <summary>
            /// Executes an async Task<T> method which has a T return type synchronously
            /// </summary>
            /// <typeparam name="T">Return Type</typeparam>
            /// <param name="task">Task<T> method to execute</param>
            /// <returns></returns>
            public static T RunSync<T>(Func<Task<T>> task)
            {
                var oldContext = SynchronizationContext.Current;
                var synch = new ExclusiveSynchronizationContext();
                SynchronizationContext.SetSynchronizationContext(synch);
                T ret = default(T);
                synch.Post(async _ =>
                {
                    try
                    {
                        ret = await task();
                    }
                    catch (Exception e)
                    {
                        synch.InnerException = e;
                        throw;
                    }
                    finally
                    {
                        synch.EndMessageLoop();
                    }
                }, null);
                synch.BeginMessageLoop();
                SynchronizationContext.SetSynchronizationContext(oldContext);
                return ret;
            }
    
            private class ExclusiveSynchronizationContext : SynchronizationContext
            {
                private bool done;
                public Exception InnerException { get; set; }
                readonly AutoResetEvent workItemsWaiting = new AutoResetEvent(false);
                readonly Queue<Tuple<SendOrPostCallback, object>> items =
                    new Queue<Tuple<SendOrPostCallback, object>>();
    
                public override void Send(SendOrPostCallback d, object state)
                {
                    throw new NotSupportedException("We cannot send to our same thread");
                }
    
                public override void Post(SendOrPostCallback d, object state)
                {
                    lock (items)
                    {
                        items.Enqueue(Tuple.Create(d, state));
                    }
                    workItemsWaiting.Set();
                }
    
                public void EndMessageLoop()
                {
                    Post(_ => done = true, null);
                }
    
                public void BeginMessageLoop()
                {
                    while (!done)
                    {
                        Tuple<SendOrPostCallback, object> task = null;
                        lock (items)
                        {
                            if (items.Count > 0)
                            {
                                task = items.Dequeue();
                            }
                        }
                        if (task != null)
                        {
                            task.Item1(task.Item2);
                            if (InnerException != null) // the method threw an exeption
                            {
                                throw new AggregateException("AsyncHelpers.Run method threw an exception.", InnerException);
                            }
                        }
                        else
                        {
                            workItemsWaiting.WaitOne();
                        }
                    }
                }
    
                public override SynchronizationContext CreateCopy()
                {
                    return this;
                }
            }
        }

    Then call it like this...

    AsyncHelpers.RunSync(() => this.MyMethodAsync());

    Apologies for the C# and the semi-colons! This is not my code originally (StackOverFlow I think), but it works perfectly.

    Nick

    Please Log in or Create an account to join the conversation.

    Last edit: by NickFriend.

    Async question 02 Mar 2023 10:01 #25490

    • wriedmann
    • wriedmann's Avatar
    • Topic Author


  • Posts: 3367
  • Hi Nick,
    thank you very much, I will try it.

    But in the meantime I have tried something other and it seems to work:
    oThread := System.Threading.Thread{ { => self:_ConnectA( cHostName, cUserName, cPassword, nPort, oConfig ) } }
    oThread:Start()
    while oThread:IsAlive
    	System.Threading.Thread.Sleep( 10 )
    end
    Using this code my debug output shows the right sequence:
    Creating AsyncFtpClient
    Creating Task Connect()
    Awaiting Task Connect()
    Task Connect() finished
    Waited 00:00:00.2349512
    Connected is True

    Is there anything that makes this code dangerous?

    Wolfgang
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    Async question 02 Mar 2023 10:19 #25491

    • NickFriend
    • NickFriend's Avatar


  • Posts: 246
  • Hi Wolfgang,

    To be honest I'm not entirely sure if there's a problem with the way you're doing it.... the only thing that occurs to me is that your code has no real means of error trapping, which is covered by the AsyncHelper class. Also it seems a bit ugly to use Sleep!

    I've been using the helper class for years now without issue (though of course by definition it's use is very limited in our app).

    Nick

    Please Log in or Create an account to join the conversation.

    Async question 02 Mar 2023 10:38 #25492

    • HansjoergP
    • HansjoergP's Avatar


  • Posts: 77
  • Hi Wolfgang,

    why you don't use "oThread:Wait()"?

    Please Log in or Create an account to join the conversation.

    Async question 02 Mar 2023 10:44 #25493

    • wriedmann
    • wriedmann's Avatar
    • Topic Author


  • Posts: 3367
  • Hi Hansjörg,

    why you don't use "oThread:Wait()"?


    I don't have that method....

    Wolfgang
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    Async question 02 Mar 2023 10:55 #25495

    • wriedmann
    • wriedmann's Avatar
    • Topic Author


  • Posts: 3367
  • Hi Nick,
    I'm now trying to translate that class to X#.
    @Robert: I remember there was a discussion about how to translate the underscore to X#:
    synch.Post(async _ =>
                {
                    try
                    {
                        await task();
                    }
                    catch (Exception e)
                    {
                        synch.InnerException = e;
                        throw;
                    }
                    finally
                    {
                        synch.EndMessageLoop();
                    }
                }, null);
    Wolfgang
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    Async question 02 Mar 2023 10:59 #25496

    • HansjoergP
    • HansjoergP's Avatar


  • Posts: 77
  • Okay. I have seen now you use Thread instead of Task. Try using the Task.Run
    learn.microsoft.com/de-de/dotnet/api/sys...w=netframework-4.7.2

    Please Log in or Create an account to join the conversation.

    Async question 02 Mar 2023 11:05 #25497

    • NickFriend
    • NickFriend's Avatar


  • Posts: 246
  • Sorry, can't help you there... can't you just leave it in a class library to avoid the pain of translation?

    Nick

    Please Log in or Create an account to join the conversation.

    Async question 02 Mar 2023 11:29 #25498

    • wriedmann
    • wriedmann's Avatar
    • Topic Author


  • Posts: 3367
  • Hi Nick,
    as temporary solution it works as separate library, but to deliver it I need to translate it to X#.
    But the good thing: it seems to work very well and simplifies my code a lot.
    Wolfgang
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    Async question 02 Mar 2023 11:31 #25499

    • wriedmann
    • wriedmann's Avatar
    • Topic Author


  • Posts: 3367
  • Hi Hansjörg,
    with Task.Run it does not works - the method does not permits that.
    It works only with a Thread, with a Task it is not executed.
    With Nicks class it works more elegantly.
    Wolfgang
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    Async question 02 Mar 2023 11:49 #25500

    • wriedmann
    • wriedmann's Avatar
    • Topic Author


  • Posts: 3367
  • Hi Robert or Chris,
    how do I translate this code from C# to X#?
    Post(_ => done = true, null);
    It is the method from this class:
    learn.microsoft.com/en-us/dotnet/api/sys...w=netframework-4.8.1
    When I write
    self:Post( { => self:done := true }, null )
    the compiler says
    error XS1593: Delegate 'System.Threading.SendOrPostCallback' does not take 0 arguments
    Thank you very much for any hint!
    Wolfgang
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    Last edit: by wriedmann.