简体   繁体   English

使用await与Task.Run,​​但UI仍然挂起几秒钟?

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

在此输入图像描述 I 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. 我正在使用SAP .NET Connector 3.0并尝试使用单独的线程登录,因此我可以让UI显示一种登录动画。

I am using Async and Await to start the login but the UI hangs for about 10 seconds during login. 我正在使用Async和Await来启动登录,但是在登录期间UI会挂起大约10秒钟。

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? 我只能想象Task中的某些东西正在使用UI?

EDIT 1: Sorry forgot to explain what GetData() does. 编辑1:抱歉忘了解释GetData()作用。 GetData() runs various reports in SAP (lots of code). GetData()在SAP中运行各种报告(大量代码)。 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. 当我看到UI挂起时,我看到它正处于“登录”阶段。 The login animation has a simple circle spinning. 登录动画有一个简单的循环旋转。 This stops part way through the login and then continues after about 5 seconds. 这将在整个登录过程中停止,然后在大约5秒后继续。

EDIT 2: The hanging seems to occour at this line here 编辑2:悬挂似乎在这条线上出现

SapRfcDestination = RfcDestinationManager.GetDestination(MyServer);

EDIT 3: Added a Photo of the threads when pausing application at the point where I see the UI hang. 编辑3:在我看到UI挂起的位置暂停应用程序时添加了线程照片。

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 . 据推测,里面什么也没有GetDataTask.Run拉姆达内SAPLogin试图回调与UI线程Dispatcher.InvokeDispatcher.BeginInvokeDispatcher.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). 注意如何Task.Factory.StartNewTaskCreationOptions.LongRunning是用来代替Task.Run以及如何GetData被卸载(尽管它已经async ,所以介意.Unwrap()在这里)。 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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM