2014-02-14 81 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

相關問題