2014-02-14 45 views
3

enter image description here我正在使用SAP .NET Connector 3.0并试图使用单独的线程登录,因此我可以使UI显示一种登录动画。在Task.Run中使用await,但UI仍然挂起几秒钟?

我使用异步和等待来启动登录,但用户界面在登录过程中挂起约10秒钟。

这里是代码,它很粗糙,因为我正在快速起草一个程序。

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; 
     }); 
}  

我只能想象任务中的某些内容正在使用UI吗?

编辑1: 对不起忘了解释GetData()做什么。 GetData()在SAP中运行各种报告(大量代码)。在视觉上,我知道它的存在是因为我的小登录动画将从“登录”变为“抓取数据”。 当我看到UI挂起时,我发现它是在“登录”阶段。登录动画有一个简单的圆圈旋转。这会在登录过程中停止,然后在大约5秒后继续。

编辑2: 悬似乎在这行这里occour

SapRfcDestination = RfcDestinationManager.GetDestination(MyServer); 

编辑3: 添加在该点暂停的应用程序时,我看到的UI线程挂起的照片。

+3

GetData是做什么的? – usr

+0

对不起,我将编辑原文,让所有人都能看到 – Gaz83

+0

注释掉整个'if'使100%确定它导致了这个(我认为它不会)。 'if(false &&等待SAPLogin())'。 – usr

回答

2

据推测,里面什么也没有GetDataTask.Run拉姆达内SAPLogin试图回调UI线程与Dispatcher.InvokeDispatcher.BeginInvokeDispatcher.InvokeAsync。首先检查这种可能性。

然后,尝试更改您的代码,如下所示。请注意如何使用Task.Factory.StartNew与​​而不是Task.Run以及如何卸载GetData(尽管它已经是async,所以请注意.Unwrap()这里)。如果有帮助,可以独立尝试每一项变更,看哪一项变更特别有帮助,或者它们是否是两者的组合。

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); 
} 
+0

我可以确认只是将SAPLogin()方法更改为您的版本可以解决问题。 – Gaz83

+0

@ Gaz83,那么我的解释是,SAP .NET Connector使用线程池中的太多线程。这么多以至于你没有多少剩余。对他们不利,对于那些真正应该做异步web服务调用的东西。要验证这一点,请检查'Process.GetCurrentProcess()。Threads.Count'并将其与'ThreadPool.GetMaxThreads'的结果进行比较。 – Noseratio

+0

现在我不确定是否将它放在正确的位置,所以我在SapRap = SapRfcDestination.Repository行后尝试了它,并得到了以下结果。 'Process.GetCurrentProcess()。Threads.Count = 21'并且调用ThreadPool.GetMaxThreads设置2个输出参数,如下所示。 'WorkerThreads = 1023'和'CompletionPortThreads = 1000' – Gaz83

相关问题