2014-02-14 65 views
0

我正在使用後臺工作器進行耗時的操作(將一些數據上傳到服務器並從服務器下載一些數據)。所有服務器的通信是通過HTTP請求(GET,POST,PUT,DELETE)和我使用的代碼是Backgroundworker和UI交互

private void btnSync_Click(object sender, RoutedEventArgs e) 
    { 
     btnSync.IsEnabled = false; 
     BackgroundWorker syncWorker = new BackgroundWorker(); 
     syncWorker.WorkerReportsProgress = true; 
     syncWorker.WorkerSupportsCancellation = true; 
     syncWorker.DoWork+=new DoWorkEventHandler(syncWorker_DoWork); 
     syncWorker.ProgressChanged+=new ProgressChangedEventHandler(syncWorker_ProgressChanged); 
     syncWorker.RunWorkerCompleted+=new RunWorkerCompletedEventHandler(syncWorker_RunWorkerCompleted); 
     syncWorker.RunWorkerAsync(); 
    } 
    private void syncWorker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     BackgroundWorker target = (BackgroundWorker)sender; 
     foreach (...........) // a loop to do some set of actions on some objects 
     { 
      target.ReportProgress(1, obj); 
      target.ReportProgress(2, obj); 
      target.ReportProgress(3, obj); 
     } 
     target.ReportProgress(4); 
    } 
    private void syncWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     if (e.ProgressPercentage == 1) 
     { 
      string id= e.UserState.ToString(); 
      mySyncHelper.DOGETFROMServer(id); //Issue a GET request and read and process resposne (deserialize json data and insert to local DB) 
     } 
     if (e.ProgressPercentage == 2) 
     { 
      string id= e.UserState.ToString(); 
      mySyncHelper.DOGETFROMServer(id);//Issue a GET request and read and process resposne(deserialize json data and insert to local DB) 
     } 
     if (e.ProgressPercentage == 3) 
     { 
      string id= e.UserState.ToString(); 
      mySyncHelper.DOGETFROMServer(id);//Issue a GET request and read and process resposne (deserialize json data and insert/Update response data to local DB) 
     } 
     if (e.ProgressPercentage ==4) 
     { 
      mySyncHelper.DOPOSTToServer();//Issue a POST request and read and process resposne (deserialize json data and insert/Update response data to local DB) 
      mySyncHelper.DOPUTToServer(); 
      mySyncHelper.DODELETEToServer(); 
     } 
    } 
    private void syncWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     if (e.Error != null) 
     { 
      txtSyncStatus.Visibility = Visibility.Visible; 
      txtSyncStatus.Text = string.Concat(DbookLanguage.message_error, Environment.NewLine , e.Error.Message.ToString()); 
     } 
     else 
     { 
      btnSync.IsEnabled = true; 
      txtSyncStatus.Text = ""; 
     } 
    } 

我現在面臨的問題是@某些階段的應用程序在等待一段時間,讓響應回來的http請求,在這種狀態下,整個應用程序進入凍結狀態。我用來獲得服務器響應的代碼是 var httpResponse =(HttpWebResponse)httpWebRequest.GetResponse(); 並且在此狀態下,應用程序無響應。

我該如何預防?是否有任何其他好方法可以使系列Http請求和應用UI交互

+0

「BackgroundWorker.ProgressChanged」和「BackgroundWorker.RunWorkerCompleted」的關鍵在於它們都在啓動工作的線程(UI線程)上運行。它封送回UI線程,以便您可以更新屏幕。但是,你正在對'BackgroundWorker.ProgressChanged'執行Blocking IO,這在UX中是一個很大的問題。你應該看看'.net 4.5'' async'' await'來代替。實現非阻塞用戶界面要容易得多。 – Aron

+0

或者,您可以將每個'mySyncHelper.DOXXXTToServer()'放入其自己的'BackgroundWorker'中。 – Aron

+0

我僅限於.net 4。在我的移動應用程序(.net - 4.5)我也使用異步等待模式。那麼我怎麼能克服這種情況。我想在這些動作發生時使UI交互 –

回答

0

正如評論中所建議的,「ProgressChanged」中的代碼在UI線程上運行,導致您的UI凍結(因爲您在此有服務器請求處理程序)。

ProgressChanged 

僅當您有一些常規的UI更新(如已完成的百分比)時,處理程序纔有用(且應該使用)。在你的情況下,考慮將你的整個代碼移動到一個新的方法(比如GetFromServer(int id)),並從DoWork內部調用這個方法。這將導致所有這些I/O工作在後臺線程上運行。