Search code examples
c#async-awaitsap-dotnet-connector

Using await with Task.Run but UI still hangs for a few seconds?


enter image description hereI am using SAP .NET Connector 3.0 and trying to login on using a separate thread so I can have the UI displaying a kind of login animation.

I am using Async and Await to start the login but the UI hangs for about 10 seconds during login.

Here is the code, its rough because I am quickly drafting a program.

async void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    Busy.Visibility = System.Windows.Visibility.Visible; // Shows progress animation

    if (await SAPLogin()) // Waits for login to finish, will always be true at the moment
    {
        await GetData(); // does things with sap

        Busy.Visibility = System.Windows.Visibility.Collapsed; // Hides progress animation
    }
 }


private Task<bool> SAPLogin()
{
    bool LoggedIn = true;

    return Task.Run(() =>
        {
           Backend = new BackendConfig();
           RfcDestinationManager.RegisterDestinationConfiguration(Backend);
           SapRfcDestination = RfcDestinationManager.GetDestination(MyServer);  // MyServer is just a string containing sever name

           SapRap = SapRfcDestination.Repository;

           BapiMD04 = SapRap.CreateFunction("MD_STOCK_REQUIREMENTS_LIST_API");

           BapiMD04.SetValue("WERKS", "140");

                return LoggedIn;
         });
}      

I can only imagine that something in the Task is using the UI?

EDIT 1: Sorry forgot to explain what GetData() does. GetData() runs various reports in SAP (lots of code). Visually, I know when its there because my little login animation will change from "Logging In" to "Grabbing Data". When I see the UI hang I see it is during the "Logging In" phase. The login animation has a simple circle spinning. This stops part way through the login and then continues after about 5 seconds.

EDIT 2: The hanging seems to occour at this line here

SapRfcDestination = RfcDestinationManager.GetDestination(MyServer);

EDIT 3: Added a Photo of the threads when pausing application at the point where I see the UI hang.


Solution

  • Presumably, nothing inside GetData or the Task.Run lambda inside SAPLogin is trying to callback the UI thread with Dispatcher.Invoke, Dispatcher.BeginInvoke or Dispatcher.InvokeAsync. Check for such possibility first.

    Then, try changing your code like below. Note how Task.Factory.StartNew with TaskCreationOptions.LongRunning is used instead of Task.Run and how GetData is offloaded (despite it's already async, so mind .Unwrap() here). If that helps, try each change independently, to see which one particularly helped, or whether it was a combination of both.

    async void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        Busy.Visibility = System.Windows.Visibility.Visible; // Shows progress animation
    
        if (await SAPLogin()) // Waits for login to finish, will always be true at the moment
        {
            //await GetData(); // does things with sap
            await Task.Factory.StartNew(() => GetData(),
                CancellationToken.None,
                TaskCreationOptions.LongRunning,
                TaskScheduler.Default).Unwrap();
    
            Busy.Visibility = System.Windows.Visibility.Collapsed; // Hides progress animation
        }
    }
    
    private Task<bool> SAPLogin()
    {
        bool LoggedIn = true;
    
        return Task.Factory.StartNew(() =>
        {
            Backend = new BackendConfig();
            RfcDestinationManager.RegisterDestinationConfiguration(Backend);
            SapRfcDestination = RfcDestinationManager.GetDestination(MyServer);  // MyServer is just a string containing sever name
    
            SapRap = SapRfcDestination.Repository;
    
            BapiMD04 = SapRap.CreateFunction("MD_STOCK_REQUIREMENTS_LIST_API");
    
            BapiMD04.SetValue("WERKS", "140");
    
            return LoggedIn;
        }, 
        CancellationToken.None,
        TaskCreationOptions.LongRunning,
        TaskScheduler.Default);
    }